Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-organize Jumpstarter packages to allow sparse dependency tree per-package #225

Merged
merged 19 commits into from
Jan 24, 2025

Conversation

kirkbrauer
Copy link
Contributor

@kirkbrauer kirkbrauer commented Jan 22, 2025

This draft PR re-organizes all Jumpstarter packages into a packages/ directory, similar to monorepos in the TS/JS ecosystem. Using uv, we can build, test, and package each one independently and provide workspace dependencies for interrelated modules.

All non-core dependencies from the main jumpstarter package have been removed and moved into separate driver/library packages so these can be consumed on an as-needed basis.

CLI packages have also been broken up by function (i.e. admin, client, exporter) to allow for separate dependencies such as kubernetes_asyncio for the admin CLI. CLI packages are marked using the jumpstarter_cli_ prefix. All CLI packages are combined into a single jumpstarter_cli metapackage to make installation easier for the end user.

The main jumpstarter package now has a very sparse dependency set:

dependencies = [
    "jumpstarter-protocol",
    "pyyaml>=6.0.2",
    "anyio>=4.4.0,!=4.6.2",
    "aiohttp>=3.10.5",
    "tqdm>=4.66.5",
    "pydantic>=2.8.2"
]

The packaging model for all drivers (including the common library) has also been standardized, removing the pyserial, opendal, and asyncclick dependencies from the core. All drivers are prefixed with jumpstarter_driver_ to indicate that they are a driver package.

Utility packages are also broken out by dependencies such as jumpstarter_kubernetes for Kubernetes primitives used by the admin CLI, jumpstarter_protocol for the gRPC protocol layer and jumpstarter_testing to make testing drivers easier.

Summary by CodeRabbit

I'll craft concise release notes focusing on the key user-facing changes and improvements.

Jumpstarter Release Notes

🚀 Major Changes

  • Restructured CLI architecture with modular command groups
  • Introduced new CLI packages for admin, client, exporter, and common utilities
  • Enhanced driver interfaces and package organization

🔧 New Features

  • Expanded CLI capabilities with more intuitive commands
  • Added new driver support for CAN, Composite, DutLink, HTTP, Network, OpenDAL, Power, PySerial, Raspberry Pi, SDWire, TFTP, and UStreamer
  • Improved testing infrastructure with new testing package

🛠 Improvements

  • Updated protocol buffer definitions
  • Enhanced error handling across drivers
  • Improved type annotations and code quality
  • Simplified configuration management

🔒 Breaking Changes

  • Significant refactoring of module imports and namespaces
  • CLI command structure has been redesigned
  • Some driver paths and configurations have been updated

📦 Package Structure

  • Created separate packages for core functionality, drivers, CLI, and testing
  • Standardized project configuration using pyproject.toml

@kirkbrauer kirkbrauer linked an issue Jan 22, 2025 that may be closed by this pull request
Copy link

coderabbitai bot commented Jan 22, 2025

Walkthrough

This pull request introduces a comprehensive reorganization of the Jumpstarter project's package structure, CLI tooling, and dependency management. The changes involve creating multiple new packages, restructuring import paths, updating configuration files, and modifying the command-line interface across various components. The primary focus is on modularizing the project, improving package organization, and standardizing the CLI experience.

Changes

File/Group Change Summary
.github/workflows/ruff.yaml Updated linter action from chartboost/ruff-action@v1 to astral-sh/ruff-action@v3
.gitignore Added .ruff_cache/ to ignore Ruff's cache directory
.pre-commit-config.yaml Changed default stages and added --fix to Ruff configuration
Makefile Reorganized targets, replaced DRIVER_TARGETS and LIB_TARGETS with PKG_TARGETS
CLI Packages Created new CLI packages: jumpstarter-cli-admin, jumpstarter-cli-client, jumpstarter-cli-exporter, jumpstarter-cli-common
Driver Packages Restructured driver packages with new naming conventions and import paths
Protocol Packages Created jumpstarter-protocol and jumpstarter-testing packages

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI
    participant Jumpstarter
    participant Drivers
    
    User->>CLI: Execute command
    CLI->>Jumpstarter: Initialize client/exporter
    Jumpstarter->>Drivers: Load specific driver
    Drivers-->>Jumpstarter: Return driver instance
    Jumpstarter-->>CLI: Provide client/exporter details
    CLI-->>User: Display results
Loading

Possibly related PRs

Suggested reviewers

  • mangelajo

Poem

🐰 A Jumpstarter's Tale of Refactoring Delight

Packages dancing, imports taking flight
CLI commands now crisp and bright
Ruff's cache hidden, workflows so clean
Modular magic, a developer's dream! 🚀

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

@mangelajo
Copy link
Member

The structure seems reasonable to me, I think we can let you present it in in the community meeting later. WDYT?

The only possible inconvenience I can imagine is the need to package lost of packages / pip / etc... but nothing where automation could not help. Also we kind of have that problem now already.

@mangelajo
Copy link
Member

I broke you into conflict again, sorry
let's remove the experimental, draft and merge asap :)

@kirkbrauer kirkbrauer changed the title EXPERIMENTAL: Re-organize Jumpstarter packages to allow sparse dependency tree per-package Re-organize Jumpstarter packages to allow sparse dependency tree per-package Jan 24, 2025
@kirkbrauer kirkbrauer marked this pull request as ready for review January 24, 2025 14:32
@mangelajo mangelajo merged commit 173b6e5 into main Jan 24, 2025
12 of 13 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (51)
packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (1)

26-26: Consider replacing the raw tuple with more descriptive fields.
Using a tuple for send/receive streams is fine, but referencing [0] and [1] may reduce clarity. Prefer a small data class or named attributes to improve readability:

- queue: Tuple[MemoryObjectSendStream[bytes], MemoryObjectReceiveStream[bytes]] = field(
-     init=False, default_factory=lambda: create_memory_object_stream[bytes](32)
- )
+ @dataclass
+ class StreamQueue:
+     sender: MemoryObjectSendStream[bytes]
+     receiver: MemoryObjectReceiveStream[bytes]

+ queue: StreamQueue = field(
+     init=False,
+     default_factory=lambda: StreamQueue(*create_memory_object_stream[bytes](32))
+ )
packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver_test.py (1)

3-4: Enhance the skip message for better debugging context.
If you encounter this skip frequently, consider including more details (e.g., where uStreamer is expected to be installed or an environment variable to set) to avoid confusion and expedite troubleshooting.

-    pytest.skip("ustreamer not available")
+    pytest.skip("uStreamer not available. Check binary path/execution environment.")
packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver_test.py (2)

10-10: Consider renaming the custom exception for clarity.
FileNotFound can be confused with Python’s built-in FileNotFoundError. Consider renaming it for clarity, such as TftpFileNotFound, to avoid overshadowing built-in exceptions.


76-77: Optionally verify cleanup of created directories.
If the intended behavior is to leave behind the new TFTP root directory after server closure, this is fine. Otherwise, consider testing removal for a full lifecycle test.

packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server_test.py (4)

61-63: Consider a more unified way to build request packets.
While multi-line string concatenation is valid, a small helper function or single line could be more readable.


88-88: Maintain a consistent style for packet creation.
This single-line approach is fine; just be sure it matches the style in similar tests.


110-110: Unify packet creation style if possible.
Optional change for consistency, as it mirrors the RRQ packet logic.


166-168: Fixed backend ensures consistent environment across tests.
Consider parameterizing if you want to test multiple backends (e.g., trio) in the future.

packages/jumpstarter-driver-http/jumpstarter_driver_http/driver_test.py (4)

18-23: Consider adding a docstring for clarity.
Although the fixture is straightforward, a short docstring explaining the purpose of yielding a temporary directory would enhance readability and maintainability.


Line range hint 24-33: Optional: Verify server readiness before yielding.
The asynchronous fixture correctly starts and stops the server. As a good practice, consider verifying that the server has fully initialized (e.g., via a health endpoint) before yielding control to tests.


Line range hint 34-71: Looks solid—consider expanding test scenarios.
This test thoroughly checks uploading, retrieving, and deleting files. You could further validate concurrency handling or error cases to strengthen coverage and ensure robustness under edge conditions.


Line range hint 78-82: Verify behavior on pre-existing directories.
The test checks that a new directory is created when it doesn’t exist. Consider also verifying behavior when the directory already exists or is inaccessible to ensure resilient error handling.

packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py (3)

3-3: Consider using a multi-line string for clarity.
Switching to triple-quoted strings (""") for EXPECTED_TABLE can improve readability when formatting multi-line outputs.


7-9: Consider adding more test coverage.
Testing multiple rows, different column orders, or missing headers can improve coverage.


10-10: Add a custom assertion message.
Adding a message like assert table == EXPECTED_TABLE, f"Got {table}, expected {EXPECTED_TABLE}" can ease debugging if the test fails.

packages/jumpstarter/conftest.py (2)

47-50: Usage of typed memory streams looks consistent.

Defining status as a tuple of send/receive streams is a clear approach. The logic for handling different states (leased, unsatisfiable, ready) appears consistent with your asynchronous requirements. If your codebase supports Python 3.9+, consider using the built-in generic form tuple[...] for stylistic consistency with the dict[str, int | str] usage below.


51-51: Maintain consistency in type annotations.

Similarly, if you are on Python 3.9 or above, consider standardizing the tuple syntax across your codebase. Below is a combined diff that updates both status and queue to the newer generic type style:

-from typing import Tuple
+# from typing import Tuple  # Remove if no longer needed

 status: Tuple[
     MemoryObjectSendStream[jumpstarter_pb2.StatusResponse],
     MemoryObjectReceiveStream[jumpstarter_pb2.StatusResponse],
 ] = field(init=False, default_factory=lambda: create_memory_object_stream[jumpstarter_pb2.StatusResponse](32))
-queue: Tuple[MemoryObjectSendStream[str], MemoryObjectReceiveStream[str]] = field(
+status: tuple[
+    MemoryObjectSendStream[jumpstarter_pb2.StatusResponse],
+    MemoryObjectReceiveStream[jumpstarter_pb2.StatusResponse],
+] = field(init=False, default_factory=lambda: create_memory_object_stream[jumpstarter_pb2.StatusResponse](32))
+queue: tuple[MemoryObjectSendStream[str], MemoryObjectReceiveStream[str]] = field(
     init=False, default_factory=lambda: create_memory_object_stream[str](32)
 )
packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py (1)

Line range hint 1-4: Review the protobuf generation workflow.

The comment "NO CHECKED-IN PROTOBUF GENCODE" suggests this generated file shouldn't be in version control. Consider:

  1. Adding this file to .gitignore
  2. Documenting the proto compilation step in the build process
  3. Ensuring CI/CD regenerates protobuf files during the build
packages/jumpstarter-driver-ustreamer/pyproject.toml (1)

Line range hint 1-41: Package structure and dependencies look good.

The package configuration aligns well with the PR objectives:

  • Follows the new jumpstarter-driver-* naming convention
  • Has minimal dependencies, only including the core jumpstarter package and required image processing library
  • Properly structured with separate dev dependencies

This is a good example of the modular package structure being implemented across Jumpstarter. The sparse dependency tree will help users by:

  • Allowing installation of only needed drivers
  • Reducing the overall dependency footprint
  • Enabling independent versioning and updates
packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py (1)

Line range hint 34-44: Consider adding timeouts and error handling for concurrent tasks.
Using a ThreadPoolExecutor ensures concurrency is tested, but if wait_for_active or wait_for_inactive fails or takes too long, the test might block indefinitely or miss the exception. Consider capturing the future’s result in a timed fashion for better error visibility.

def test_drivers_gpio_digital_input():
    instance = DigitalInput(pin=4)

    with serve(instance) as client:
        with ThreadPoolExecutor() as pool:
-            pool.submit(client.wait_for_active)
+            future = pool.submit(client.wait_for_active)
+            instance.device.pin.drive_high()
+            future.result(timeout=5)

        with ThreadPoolExecutor() as pool:
-            pool.submit(client.wait_for_inactive)
+            future = pool.submit(client.wait_for_inactive)
+            instance.device.pin.drive_low()
+            future.result(timeout=5)
packages/jumpstarter-cli/jumpstarter_cli/cli_test.py (1)

7-15: Check exit code in tests.
In addition to verifying the output, consider asserting that result.exit_code == 0 to fully confirm success.

 async def test_cli():
     runner = CliRunner()
     result = await runner.invoke(jmp, [])
+    assert result.exit_code == 0, f"Expected exit code 0, got {result.exit_code}"
     assert "admin" in result.output
     assert "client" in result.output
     assert "exporter" in result.output
     assert "version" in result.output
packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py (2)

1-2: Use descriptive alias or consistent naming.
While the alias click for asyncclick is common, consider using import asyncclick exclusively or another clear alias (like aclick) to differentiate between the traditional click library and asyncclick. This makes import sources unambiguous for collaborators.


23-24: Use console_scripts for distribution.
Although if __name__ == "__main__": admin() is standard, consider defining an entry point through setup.py or pyproject.toml. This facilitates easy installation and usage (jumpstarter-admin CLI, for example).

packages/jumpstarter-cli-common/jumpstarter_cli_common/opt.py (2)

3-9: Provide default log level for clarity.
Currently, if no log level is specified, the code may have undefined or framework-dependent behavior. Consider defaulting to "INFO" to maintain consistent logging behavior.

-    type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]),
-    help="Set the log level",
+    type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]),
+    default="INFO",
+    help="Set the log level (default: INFO)",

11-13: Handle missing kubeconfig gracefully.
When no kubeconfig is provided (default=None), consider adding a handler to inform the user or automatically pick up a default path in their environment (e.g., ~/.kube/config) to improve user experience.

packages/jumpstarter/jumpstarter/common/condition.py (1)

6-8: Consider adding a docstring for clarity.

While this function is straightforward, adding a brief docstring about the intended usage and the significance of the reason parameter would improve readability and maintainability.

packages/jumpstarter-cli-client/jumpstarter_cli_client/__init__.py (2)

10-13: Provide usage examples in the docstring.

The short docstring is fine, but consider appending an example usage snippet or subcommand overview to help new contributors quickly understand the client CLI group.


15-18: Clarify the purpose of function j() and align entry points.

There's a second entry point in j(), but if __name__ == "__main__": client() also launches the CLI. Consider unifying these to avoid confusion.

packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/__init__.py (2)

11-13: Add short usage note in docstring.

Similar to the client CLI, consider adding a brief example usage for exporter.


15-19: Potential for advanced logging configuration.

If more complex logging is required, consider a dedicated logging module or configurable logging format.

packages/jumpstarter-cli-client/jumpstarter_cli_client/client_shell.py (1)

14-14: Enhance type annotations.

labels is typed loosely in the parameter list. Consider adding a more explicit type annotation (e.g., list[tuple[str, str]]) for clarity, especially since you cast it to dict internally.

packages/jumpstarter-cli-common/jumpstarter_cli_common/alias.py (1)

34-36: Improve Multiple-Match Handling
When multiple command aliases collide, the code fails with “Too many matches.” You may want to provide a more user-friendly fallback or prompt the user to choose among the matching commands.

packages/jumpstarter-driver-tftp/examples/tftp_test.py (1)

14-15: Refactor Fixture Usage
test_tftp_upload is annotated with @pytest.fixture() yet contains the entire test logic. Typically, fixtures set up resources and return them for test functions. It’s more conventional to have a dedicated test function that uses data or environment prepared by a fixture.

A possible approach:

- @pytest.fixture()
- def test_tftp_upload(self, client):
+ @pytest.fixture()
+ def tftp_server_fixture(client):
    # set up TFTP server
    # yield / return resources
    # tear down TFTP server

def test_tftp_upload(tftp_server_fixture):
    # actual test logic here
packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_test.py (1)

30-30: Interactive “create-config”
Using interactive prompts for missing options shows a good user experience. Ensure test coverage includes edge cases.

packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_config.py (3)

9-10: Avoid capturing tokens via interactive prompt
Prompting for tokens in plain text can pose a security risk, especially if logs or shell history are retained. Consider safer alternatives, such as reading from an environment variable or using a non-echoing prompt.


12-20: Enforce type hints for function arguments
Adding type hints (e.g., def create_exporter_config(alias: str, endpoint: str, token: str) -> None:) can improve readability, tooling, and maintenance.


51-63: Consider pagination or filtering for large configurations
When dealing with many configs, displaying them all at once may overwhelm users. Additional filtering or pagination can enhance usability.

packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter.py (3)

1-4: Consider grouping or reordering imports.
Combining standard library imports (sys, traceback, pathlib) clearly at the top, then third-party, can improve readability.


9-14: Consider collecting CLI arguments into a single module or file.
This approach might make the CLI definition more discoverable and easier to maintain.


28-42: Add test coverage to ensure error conditions are well-handled.
The run_exporter function gracefully raises ClickException if the exporter is missing. Verify coverage for config path success/failure scenarios.

packages/jumpstarter-cli-client/jumpstarter_cli_client/client_test.py (3)

5-5: Remove relative imports if not strictly needed.
Using absolute imports can improve clarity, but this is optional.


27-28: Ensure duplicate creation scenario is tested thoroughly.
The test checks the non-zero exit code. Confirm that the returned error message is also validated.


35-35: Validate interactive input coverage.
Consider adding more tests for other interactive flows or invalid user input.

packages/jumpstarter-testing/jumpstarter_testing/pytest.py (1)

51-51: Default filter labels.
Consider a default empty dict to avoid errors if a subclass doesn’t set filter_labels.

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py (1)

11-11: Confirm string manipulation logic.
Stripping the leading “v” from major version is valid if your versioning scheme always includes it.

packages/jumpstarter-cli-client/jumpstarter_cli_client/client_config.py (1)

67-82: Consider adding a brief docstring to clarify the function's purpose.
set_next_client lacks direct documentation. A short description can help maintainers and newcomers.

+"""
+Selects the next available client as the current one if the specified client is removed.
+"""
packages/jumpstarter/jumpstarter/client/lease.py (1)

28-28: Add explanatory comments for the release field.
Its default to True is sensible. A quick docstring or comment can clarify the implications of changing it.

+# Indicates whether the lease should be automatically released when exiting context
 release: bool = True  # release on contexts exit
packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py (1)

171-171: Ensure consistency with get_reason
make_lease_row relies on get_reason(lease). If get_reason may return None or unexpected values, consider a fallback or validation here to avoid incomplete data in the row.

packages/jumpstarter-testing/pyproject.toml (1)

5-5: Consider adding more authors if applicable.

Other package files in the repository typically list multiple authors. Consider adding other contributors if they've worked on the testing utilities.

Makefile (1)

38-39: Consider adding a description for the generate target.

While the generate target is a good addition, it would be helpful to add a comment explaining its purpose and the expected output of buf generate.

+# Generate protocol buffers code using buf
 generate:
     buf generate
packages/jumpstarter-driver-http/jumpstarter_driver_http/driver.py (1)

Line range hint 174-178: Consider adding error handling for site.start().

The server start operation could fail due to port conflicts or network issues. Consider adding explicit error handling.

         await self.runner.setup()

         site = web.TCPSite(self.runner, self.host, self.port)
-        await site.start()
-        logger.info(f"HTTP server started at http://{self.host}:{self.port}")
+        try:
+            await site.start()
+            logger.info(f"HTTP server started at http://{self.host}:{self.port}")
+        except Exception as e:
+            logger.error(f"Failed to start HTTP server: {e}")
+            await self.runner.cleanup()
+            self.runner = None
+            raise HttpServerError(f"Failed to start HTTP server: {e}") from e
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f5fe9a0 and b6b933b.

⛔ Files ignored due to path filters (3)
  • packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_a.jpeg is excluded by !**/*.jpeg
  • packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_b.jpeg is excluded by !**/*.jpeg
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (157)
  • .github/workflows/ruff.yaml (1 hunks)
  • .gitignore (1 hunks)
  • .pre-commit-config.yaml (1 hunks)
  • Makefile (3 hunks)
  • __templates__/create_driver.sh (2 hunks)
  • __templates__/driver/pyproject.toml.tmpl (1 hunks)
  • buf.gen.yaml (1 hunks)
  • contrib/drivers/http/.gitignore (0 hunks)
  • contrib/drivers/http/.python-version (0 hunks)
  • contrib/drivers/tftp/.gitignore (0 hunks)
  • contrib/drivers/tftp/.python-version (0 hunks)
  • examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py (2 hunks)
  • examples/soc-pytest/pyproject.toml (1 hunks)
  • jumpstarter/__main__.py (0 hunks)
  • jumpstarter/cli/client.py (0 hunks)
  • jumpstarter/cli/exporter.py (0 hunks)
  • jumpstarter/cli/jmp.py (0 hunks)
  • jumpstarter/cli/util/opt.py (0 hunks)
  • jumpstarter/client/adapters/__init__.py (0 hunks)
  • jumpstarter/testing/pytest.py (0 hunks)
  • packages/jumpstarter-cli-admin/README.md (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete_test.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py (3 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py (2 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py (2 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res_test.py (2 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/k8s.py (1 hunks)
  • packages/jumpstarter-cli-admin/pyproject.toml (1 hunks)
  • packages/jumpstarter-cli-client/README.md (1 hunks)
  • packages/jumpstarter-cli-client/jumpstarter_cli_client/__init__.py (1 hunks)
  • packages/jumpstarter-cli-client/jumpstarter_cli_client/client_config.py (1 hunks)
  • packages/jumpstarter-cli-client/jumpstarter_cli_client/client_shell.py (1 hunks)
  • packages/jumpstarter-cli-client/jumpstarter_cli_client/client_test.py (2 hunks)
  • packages/jumpstarter-cli-client/jumpstarter_cli_client/lease.py (1 hunks)
  • packages/jumpstarter-cli-client/pyproject.toml (1 hunks)
  • packages/jumpstarter-cli-common/README.md (1 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/__init__.py (2 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/alias.py (1 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/opt.py (1 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py (1 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/version.py (1 hunks)
  • packages/jumpstarter-cli-common/pyproject.toml (1 hunks)
  • packages/jumpstarter-cli-exporter/README.md (1 hunks)
  • packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/__init__.py (1 hunks)
  • packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter.py (1 hunks)
  • packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_config.py (1 hunks)
  • packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_test.py (1 hunks)
  • packages/jumpstarter-cli-exporter/pyproject.toml (1 hunks)
  • packages/jumpstarter-cli/README.md (1 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/__init__.py (1 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/__main__.py (1 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/cli_test.py (1 hunks)
  • packages/jumpstarter-cli/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-can/jumpstarter_driver_can/client.py (1 hunks)
  • packages/jumpstarter-driver-can/jumpstarter_driver_can/client_test.py (1 hunks)
  • packages/jumpstarter-driver-can/jumpstarter_driver_can/driver.py (1 hunks)
  • packages/jumpstarter-driver-can/pyproject.toml (2 hunks)
  • packages/jumpstarter-driver-composite/README.md (1 hunks)
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (0 hunks)
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver.py (1 hunks)
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-composite/pyproject.toml (2 hunks)
  • packages/jumpstarter-driver-dutlink/examples/dutlink.py (1 hunks)
  • packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (1 hunks)
  • packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-dutlink/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-http/jumpstarter_driver_http/client.py (2 hunks)
  • packages/jumpstarter-driver-http/jumpstarter_driver_http/driver.py (3 hunks)
  • packages/jumpstarter-driver-http/jumpstarter_driver_http/driver_test.py (3 hunks)
  • packages/jumpstarter-driver-http/pyproject.toml (2 hunks)
  • packages/jumpstarter-driver-network/README.md (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/__init__.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/fabric_test.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc_test.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/portforward.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/__init__.py (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (2 hunks)
  • packages/jumpstarter-driver-network/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-opendal/README.md (1 hunks)
  • packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/adapter.py (1 hunks)
  • packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py (1 hunks)
  • packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver.py (1 hunks)
  • packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-opendal/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-power/README.md (1 hunks)
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (0 hunks)
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/client_test.py (1 hunks)
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (3 hunks)
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-power/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-pyserial/README.md (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/console.py (2 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver_test.py (4 hunks)
  • packages/jumpstarter-driver-pyserial/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver.py (1 hunks)
  • packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py (2 hunks)
  • packages/jumpstarter-driver-raspberrypi/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver.py (1 hunks)
  • packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-sdwire/pyproject.toml (2 hunks)
  • packages/jumpstarter-driver-tftp/examples/exporter.yaml (1 hunks)
  • packages/jumpstarter-driver-tftp/examples/tftp_test.py (1 hunks)
  • packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/client.py (1 hunks)
  • packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver.py (4 hunks)
  • packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver_test.py (3 hunks)
  • packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server.py (16 hunks)
  • packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server_test.py (11 hunks)
  • packages/jumpstarter-driver-tftp/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/client.py (1 hunks)
  • packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver.py (0 hunks)
  • packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-ustreamer/pyproject.toml (1 hunks)
  • packages/jumpstarter-imagehash/jumpstarter_imagehash/imagehash.py (2 hunks)
  • packages/jumpstarter-imagehash/pyproject.toml (1 hunks)
  • packages/jumpstarter-kubernetes/README.md (1 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (1 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients_test.py (1 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (1 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py (1 hunks)
  • packages/jumpstarter-kubernetes/pyproject.toml (1 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/__init__.py (1 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py (3 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py (1 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py (2 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py (2 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py (1 hunks)
  • packages/jumpstarter-protocol/protocol_test.py (1 hunks)
  • packages/jumpstarter-protocol/pyproject.toml (1 hunks)
  • packages/jumpstarter-testing/conftest.py (1 hunks)
  • packages/jumpstarter-testing/jumpstarter_testing/__init__.py (1 hunks)
  • packages/jumpstarter-testing/jumpstarter_testing/pytest.py (1 hunks)
  • packages/jumpstarter-testing/jumpstarter_testing/pytest_test.py (1 hunks)
  • packages/jumpstarter-testing/pyproject.toml (1 hunks)
  • packages/jumpstarter/README.md (1 hunks)
  • packages/jumpstarter/conftest.py (3 hunks)
  • packages/jumpstarter/jumpstarter/client/base.py (1 hunks)
  • packages/jumpstarter/jumpstarter/client/client.py (1 hunks)
  • packages/jumpstarter/jumpstarter/client/core.py (1 hunks)
  • packages/jumpstarter/jumpstarter/client/lease.py (4 hunks)
  • packages/jumpstarter/jumpstarter/common/condition.py (1 hunks)
  • packages/jumpstarter/jumpstarter/common/streams.py (1 hunks)
  • packages/jumpstarter/jumpstarter/common/utils.py (2 hunks)
  • packages/jumpstarter/jumpstarter/config/__init__.py (1 hunks)
  • packages/jumpstarter/jumpstarter/config/client.py (4 hunks)
  • packages/jumpstarter/jumpstarter/config/client_config_test.py (1 hunks)
  • packages/jumpstarter/jumpstarter/config/env.py (1 hunks)
  • packages/jumpstarter/jumpstarter/config/exporter.py (4 hunks)
⛔ Files not processed due to max files limit (10)
  • packages/jumpstarter/jumpstarter/config/exporter_test.py
  • packages/jumpstarter/jumpstarter/config/user_config_test.py
  • packages/jumpstarter/jumpstarter/driver/base.py
  • packages/jumpstarter/jumpstarter/exporter/exporter.py
  • packages/jumpstarter/jumpstarter/exporter/session.py
  • packages/jumpstarter/jumpstarter/listener_test.py
  • packages/jumpstarter/jumpstarter/streams/init.py
  • packages/jumpstarter/jumpstarter/streams/router.py
  • packages/jumpstarter/pyproject.toml
  • pyproject.toml
💤 Files with no reviewable changes (14)
  • contrib/drivers/http/.gitignore
  • jumpstarter/main.py
  • contrib/drivers/tftp/.python-version
  • contrib/drivers/http/.python-version
  • contrib/drivers/tftp/.gitignore
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py
  • jumpstarter/cli/client.py
  • jumpstarter/cli/jmp.py
  • packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver.py
  • jumpstarter/testing/pytest.py
  • jumpstarter/client/adapters/init.py
  • jumpstarter/cli/util/opt.py
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py
  • jumpstarter/cli/exporter.py
✅ Files skipped from review due to trivial changes (64)
  • packages/jumpstarter-driver-network/README.md
  • packages/jumpstarter-cli-client/README.md
  • packages/jumpstarter-cli-admin/README.md
  • packages/jumpstarter-driver-power/README.md
  • packages/jumpstarter-kubernetes/README.md
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients_test.py
  • packages/jumpstarter-driver-composite/README.md
  • packages/jumpstarter-cli-common/README.md
  • packages/jumpstarter-driver-pyserial/README.md
  • packages/jumpstarter-testing/jumpstarter_testing/init.py
  • packages/jumpstarter-driver-opendal/README.md
  • packages/jumpstarter-cli/README.md
  • packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/client.py
  • .gitignore
  • packages/jumpstarter/jumpstarter/config/env.py
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/version.py
  • packages/jumpstarter/jumpstarter/common/utils.py
  • packages/jumpstarter-cli-exporter/README.md
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/k8s.py
  • packages/jumpstarter/jumpstarter/client/client.py
  • packages/jumpstarter-driver-http/jumpstarter_driver_http/client.py
  • packages/jumpstarter/jumpstarter/common/streams.py
  • packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver.py
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc.py
  • packages/jumpstarter-protocol/protocol_test.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py
  • packages/jumpstarter-driver-can/jumpstarter_driver_can/driver.py
  • packages/jumpstarter/jumpstarter/client/base.py
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/portforward.py
  • packages/jumpstarter-driver-power/pyproject.toml
  • packages/jumpstarter/README.md
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/console.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/init.py
  • packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/client.py
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py
  • packages/jumpstarter-cli-admin/pyproject.toml
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/client_test.py
  • packages/jumpstarter-cli-common/pyproject.toml
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/driver_test.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete_test.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete.py
  • packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py
  • packages/jumpstarter-protocol/jumpstarter_protocol/init.py
  • packages/jumpstarter/jumpstarter/config/client_config_test.py
  • packages/jumpstarter-imagehash/jumpstarter_imagehash/imagehash.py
  • packages/jumpstarter-driver-pyserial/pyproject.toml
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py
  • packages/jumpstarter-driver-opendal/pyproject.toml
  • packages/jumpstarter-protocol/pyproject.toml
  • packages/jumpstarter-driver-dutlink/pyproject.toml
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver_test.py
  • packages/jumpstarter-cli-exporter/pyproject.toml
  • packages/jumpstarter-kubernetes/pyproject.toml
  • packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server.py
  • packages/jumpstarter-driver-network/pyproject.toml
  • packages/jumpstarter-cli/pyproject.toml
  • packages/jumpstarter-cli-client/pyproject.toml
🧰 Additional context used
🪛 Ruff (0.8.2)
packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py

29-29: Module level import not at top of file

(E402)


29-29: .kubernetes_pb2 imported but unused

Remove unused import: .kubernetes_pb2

(F401)

🔇 Additional comments (163)
packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (1)

3-3: Good use of explicit imports for type annotations.
Leveraging Tuple from typing clarifies code intent and ensures compatibility with Python versions < 3.9. For Python ≥ 3.9, you could also use built-in generic types (e.g., tuple[str, str]) if the codebase supports it.

packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver_test.py (2)

8-8: Use of serve function looks appropriate.

The serve function from jumpstarter.common.utils is used in a context manager, which neatly manages resources for the test. This ensures consistent setup and teardown of the mocked environment, helping maintain test isolation.


11-11: Local relative import is well-aligned with package structure.

Switching to a relative import (from .driver import MockStorageMux) can enhance maintainability when reorganizing or refactoring local modules. Continue to verify that downstream references of MockStorageMux are updated consistently across the package.

packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver.py (2)

2-2: No issues with the import statement.

Importing dataclass from pydantic.dataclasses is valid and aligns with typical usage patterns.


8-8: Verify correct module path.

Changing the return string to "jumpstarter_driver_composite.client.CompositeClient" appears consistent with the new structure. However, ensure that the referenced CompositeClient class indeed resides in that module path, and that all accessories (like type checking or instance creation) still function properly across the codebase.

Here's a script to quickly confirm that CompositeClient is defined in the target file:

✅ Verification successful

Module path verification successful

The CompositeClient class is correctly defined in jumpstarter_driver_composite/client.py and the module path jumpstarter_driver_composite.client.CompositeClient accurately reflects its location in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
ast-grep --pattern $'class CompositeClient($_) {\n $$$\n}' 

Length of output: 57


Script:

#!/bin/bash
# Find the client.py file
echo "Looking for client.py:"
fd client.py

echo -e "\nChecking file contents if found:"
fd client.py -x cat {}

echo -e "\nSearching for CompositeClient references:"
rg "CompositeClient" -A 2

Length of output: 30198

packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver.py (1)

12-12: Confirm the existence of StorageMuxClient in the new path.

This change updates the returned string to "jumpstarter_driver_opendal.client.StorageMuxClient". Please verify that the StorageMuxClient class is indeed defined and publicly accessible at the specified location to avoid runtime import errors or missing references.

✅ Verification successful

StorageMuxClient exists and is accessible at the specified path

The class is properly defined in jumpstarter_driver_opendal/client.py and can be imported using the provided import path.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching for the StorageMuxClient definition to confirm its presence and spelling
rg -A 5 'class StorageMuxClient'

Length of output: 621

packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver_test.py (4)

22-28: Evaluate synchronous vs. asynchronous tear-down.
If Tftp has asynchronous internals, consider making this fixture async and ensuring .close() handles async context properly. Otherwise, this is a clean fixture setup.


Line range hint 29-67: Comprehensive file operation tests, but watch concurrency.
This test robustly verifies file creation, streaming, listing, and deletion. However, the server.resources assignment suggests potential concurrency concerns. Confirm that server handles concurrent file operations safely in real scenarios.


69-74: Straightforward host config test.
This test effectively verifies custom host settings. No immediate issues spotted.


79-79: Consistent style for the anyio backend fixture.
Switching to "asyncio" ensures consistency. This is good to see.

packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server_test.py (9)

17-17: Great ephemeral port usage.
Assigning port=0 ensures less port collision risk and is perfect for testing.


28-28: Looks consistent with the Python documentation for creating a datagram endpoint.
No concerns here.


33-33: Transition to anyio is consistent with recent changes.
This marker integrates well with the asynchronous testing setup.


49-49: Use of anyio aligns with broader async test refactoring.
Good choice for uniformity across test cases.


101-101: Good use of anyio in write request rejection test.
This remains consistent with the asynchronous test design.


123-123: Glad to see anyio used here as well.
No issues with test logic.


131-131: Invalid packet handling test is straightforward and clear.
This approach effectively checks server resilience.


142-142: Asynchronous path traversal test is aligned with the rest of the suite.
Well done reinforcing secure coding practices.


153-153: Excellent test coverage for path traversal edge cases.
No concerns with the logic.

packages/jumpstarter-driver-http/jumpstarter_driver_http/driver_test.py (1)

72-77: Optional: Confirm actual binding to the configured host.
Currently, the test only asserts the stored host property. You might also consider adding a smoke test ensuring the server can successfully bind and is reachable on that host if feasible within your test environment.

packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py (3)

1-2: No issues with the import.
It is clear and references the correct relative module.


4-5: Blank lines observed.
Skipping since these lines just provide spacing.


6-6: Test function name looks good.
Its naming follows standard conventions, ensuring that tools like pytest/unittest correctly detect and run it.

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

Line range hint 1-38: Well-structured package configuration!

The package configuration follows best practices:

  • Standardized driver package naming
  • Clear dependency categorization (main vs dev)
  • Modern Python version requirement
  • Pinned dependency versions

30-30: Verify path consistency across driver packages.

The path change from '../../../' to '../../' aligns with the PR objective of reorganizing packages into a dedicated packages/ directory.

Let's verify this change is consistent across all driver packages:

✅ Verification successful

Path is consistent across all driver packages

All 12 driver packages in the repository use raw-options = { 'root' = '../../'}, confirming this is the correct standardized path relative to the repository root.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check raw-options root path in all driver package pyproject.toml files
# Expected: All paths should be set to '../../'

echo "Checking raw-options root path in driver packages..."
fd --type f "pyproject.toml" packages/jumpstarter-driver- --exec grep -H "raw-options.*root.*" {} \;

Length of output: 334


Script:

#!/bin/bash
# First, let's understand the repository structure
echo "=== Repository Structure ==="
ls -la

echo -e "\n=== Finding all pyproject.toml files ==="
fd pyproject.toml

Length of output: 2824


Script:

#!/bin/bash
# Check raw-options root path in all driver packages
echo "=== Checking raw-options root paths ==="
for pkg in packages/jumpstarter-driver-*/pyproject.toml; do
    echo "=== $pkg ==="
    grep -A 1 "raw-options" "$pkg" || echo "No raw-options found"
done

Length of output: 3628

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

31-32: Verify VCS root path aligns with new package structure.

The change in VCS root path from '../../../' to '../../' suggests the package is now two levels deep instead of three, which aligns with the PR objective of restructuring packages into a dedicated packages/ directory.

Let's verify the new directory structure:

✅ Verification successful

VCS root path correctly aligned with new package structure

The path change from '../../../' to '../../' is correct as the package is now exactly two levels deep under the dedicated packages/ directory.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the package's location in the new directory structure

# Check if the package is at the expected depth
test -f packages/jumpstarter-driver-can/pyproject.toml && echo "Package is at correct depth" || echo "Package not found at expected location"

# List directory structure to verify
tree -L 3 packages/

Length of output: 5253


15-15: Verify compatibility with python-can 4.5.0.

The dependency version bump from 4.4.2 to 4.5.0 may introduce breaking changes.

Let's check the changelog and any known issues:

✅ Verification successful

Dependency update to python-can 4.5.0 appears safe

The version bump from 4.4.2 to 4.5.0 follows semantic versioning conventions, suggesting backward compatibility. While there are some reported issues with specific hardware interfaces (LAWICEL, BLF files), no breaking changes affecting core functionality have been identified.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check python-can changelog and PyPI info for breaking changes

# Get release info from PyPI
curl -s https://pypi.org/pypi/python-can/json | jq -r '.releases["4.5.0"] | select(.)'

# Check GitHub releases for breaking changes
gh api repos/hardbyte/python-can/releases/tags/4.5.0 --jq '.body'

Length of output: 1985


Script:

#!/bin/bash
# Try to find changelog information from multiple sources

# Check for CHANGELOG.md content
gh api repos/hardbyte/python-can/contents/CHANGELOG.md --raw 2>/dev/null

# Search for issues/discussions mentioning 4.5.0
gh api search/issues -X GET -f q="repo:hardbyte/python-can 4.5.0 in:title,body" --jq '.items[] | {title: .title, body: .body, html_url: .html_url}' 2>/dev/null

# Try to get the commit history around the release
gh api repos/hardbyte/python-can/commits -X GET -f sha=4.5.0 --jq '.[0,1,2] | {message: .commit.message, sha: .sha}' 2>/dev/null

Length of output: 6928

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

30-30: LGTM: Root path update aligns with new package structure.

The modification of raw-options.root from '../../../' to '../../' correctly reflects the move to the new packages directory structure.


13-13: Consider pinning the jumpstarter-driver-opendal dependency version.

While adding the OpenDAL driver dependency aligns with the package reorganization, not specifying a version constraint could lead to compatibility issues.

Let's check the available versions and current usage:

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

13-13: Consider pinning the jumpstarter-driver-opendal dependency version.

Similar to other driver packages, consider specifying a version constraint for better dependency management.


18-18: LGTM: Root path update aligns with new package structure.

The modification of raw-options.root from '../../../' to '../../' correctly reflects the move to the new packages directory structure.

packages/jumpstarter/conftest.py (2)

5-5: Good addition for type clarity.

Importing Tuple improves the readability of type annotations, making it explicit for future maintainers.


18-18: Import statement consistency check.

This import from jumpstarter_protocol aligns with the reorganized package structure introduced in the PR. Ensure all references conform to the new structure to avoid import path collisions or confusion.

packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver.py (1)

12-12: Ensure interface consistency after changing the import source.

By switching the StorageMuxInterface import from the old jumpstarter.drivers.storage.driver module to the new jumpstarter_driver_opendal.driver module, confirm that all references across the codebase now align with the new no-longer-centralized location. This helps avoid any runtime errors or confusion about which StorageMuxInterface definition is in use.

Below is a shell script you can run from the repository root to identify any lingering references to the old import path:

✅ Verification successful

Import source change is complete and consistent

The StorageMuxInterface import has been successfully migrated to jumpstarter_driver_opendal.driver across all implementations, with no remaining references to the old import path.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any leftover references to `StorageMuxInterface` from the old path.
rg "from jumpstarter\.drivers\.storage\.driver import StorageMuxInterface" -A 5

Length of output: 81


Script:

#!/bin/bash
# Search for any remnants of the old import path with more flexible patterns
rg -i "jumpstarter\.drivers\.storage\.driver.*StorageMuxInterface"

# Search for the new import path
rg "jumpstarter_driver_opendal\.driver.*StorageMuxInterface"

# Find all occurrences of StorageMuxInterface
rg "StorageMuxInterface"

# Use ast-grep to find interface implementations
ast-grep --pattern 'class $_ (StorageMuxInterface):'

Length of output: 1262

packages/jumpstarter-driver-tftp/pyproject.toml (5)

Line range hint 1-44: Overall package configuration aligns with restructuring goals.

The changes support the PR's objective of modularizing Jumpstarter packages, but there are a few areas that need attention:

  1. Dependency version constraints need standardization
  2. Build configuration paths need verification
  3. Test configuration strategy needs clarification

These refinements will help ensure consistency across the restructured packages.


29-29: Verify the root path adjustment across all packages.

The root path has been changed from '../../../' to '../../'. Let's ensure this is consistent with other packages in the new structure.

Run this script to check path consistency:

✅ Verification successful

Root path configuration is consistent across all packages

All packages in the repository consistently use '../../' as the root path, which is correct for the new package structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check root path configuration across all packages
echo "Checking root path configuration in all pyproject.toml files:"
fd -g "pyproject.toml" -x grep -H "root.*=.*\.\." {}

Length of output: 2058


35-40: Clarify the removal of pytest configuration.

The pytest configuration has been commented out, including important settings for:

  • Coverage reporting
  • Logging configuration
  • Async mode settings

This might impact test execution and coverage reporting. Are these settings being moved to a shared configuration?

Run this script to check pytest configuration across packages:

✅ Verification successful

Pytest configuration removal is acceptable

The commented-out configuration appears redundant as other packages in the repository maintain their own active pytest configurations with proper coverage reporting, logging, and async settings. The presence of --cov-append in another package suggests a coordinated coverage reporting strategy is in place.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check pytest configuration across packages
echo "Checking pytest configuration in all pyproject.toml files:"
fd -g "pyproject.toml" -x grep -A 5 "\[tool\.pytest" {}

Length of output: 714


13-13: Specify version constraint for jumpstarter-driver-opendal dependency.

Other dependencies have version constraints, but jumpstarter-driver-opendal doesn't. This could lead to compatibility issues.

Run this script to check the latest version:


19-23: Standardize version constraints in dev dependencies.

There are inconsistencies in version constraints:

  • pytest-anyio>=0.0.0 and pytest-asyncio>=0.0.0 have unusually low version constraints
  • jumpstarter-testing lacks a version constraint

Run this script to check the latest versions and current usage:

packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py (1)

5-5: Verify compatibility with the updated protobuf version.

The protobuf Python version has been updated from 5.28.2 to 5.29.3. While this is a minor version bump, it's important to ensure compatibility across the codebase.

✅ Verification successful

Protobuf version update is compatible with package requirements

The update to protobuf 5.29.3 in the generated file aligns with the package's dependency specification (protobuf>=5.29.3) defined in packages/jumpstarter-protocol/pyproject.toml. No compatibility issues were found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check protobuf version requirements across the codebase
# Look for any explicit protobuf version requirements in setup.py files and requirements files

echo "Checking setup.py files for protobuf requirements..."
fd -e py -g 'setup.py' --exec rg -l 'protobuf'

echo "Checking requirements files for protobuf requirements..."
fd -g '*requirements*.txt' --exec rg -l 'protobuf'

Length of output: 333


Script:

#!/bin/bash
# Broader search for protobuf-related files and version specifications

echo "Searching for protobuf-related files..."
rg -l -i "protobuf|protoc" --type-add 'config:*.{json,toml,yaml,yml}' --type config --type python

echo -e "\nSearching for specific version patterns..."
rg -i "protobuf.*=.*[0-9]+\.[0-9]+\.[0-9]|protoc.*version|proto.*version" --type-add 'config:*.{json,toml,yaml,yml}' --type config --type python

Length of output: 498


Script:

#!/bin/bash
# Search for protobuf-related files and version specifications with corrected syntax

echo "Searching for protobuf-related files..."
rg -l -i "protobuf|protoc" -g '*.{py,txt,json,toml,yaml,yml}'

echo -e "\nSearching for version patterns..."
rg -i "protobuf.*=.*[0-9]" -g '*.{py,txt,json,toml,yaml,yml}'

echo -e "\nChecking content of any pyproject.toml files..."
fd -e toml -x cat {}

echo -e "\nChecking content of any requirements files..."
fd -g '*requirements*.txt' -x cat {}

Length of output: 32333

packages/jumpstarter-driver-ustreamer/pyproject.toml (1)

30-30: Verify the VCS root path is correct after package reorganization.

The path change from '../../../' to '../../' aligns with the PR's package restructuring goals. Let's verify this is correct:

✅ Verification successful

VCS root path '../../' is correct and consistent with project structure

The path change aligns with the repository's organization where all driver packages are under the packages/ directory. This is verified by the consistent use of the same VCS root configuration across all driver packages in the project.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the VCS root path is correct for the new package structure

# Check if we're in the expected directory structure
if [ -d "packages/jumpstarter-driver-ustreamer" ]; then
  echo "Package is in the correct location"
  
  # Verify the root contains the expected VCS files
  if [ -f "../../.git/config" ]; then
    echo "VCS root path '../../' is correct"
  else
    echo "Error: VCS root path '../../' appears incorrect"
  fi
else
  echo "Error: Package not found in expected location"
fi

# List all similar pyproject.toml files to verify consistency
echo -e "\nChecking other driver packages for consistency:"
fd pyproject.toml packages/jumpstarter-driver- --exec grep -l "raw-options.*root.*../../"

Length of output: 590


Script:

#!/bin/bash
# Check repository structure and pyproject.toml files

echo "Current directory contents:"
ls -la

echo -e "\nSearching for all pyproject.toml files:"
fd pyproject.toml

echo -e "\nChecking git root directory:"
git rev-parse --show-toplevel

echo -e "\nChecking all directory structure:"
find . -type d -maxdepth 3

Length of output: 5903


Script:

#!/bin/bash
# Check raw-options configuration in other driver packages
echo "Checking raw-options configuration in driver packages:"
for f in packages/jumpstarter-driver-*/pyproject.toml; do
    echo -e "\n=== $f ==="
    grep -A 1 "raw-options" "$f" || echo "No raw-options found"
done

Length of output: 3706

packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py (1)

6-6: Confirm consistent naming and imports across the new package structure.
The import path appears correct and aligns with the reorganization goals. However, please verify there are no remaining references to the old import paths in the codebase.

You can run the following script to locate remaining references:

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

8-8: Confirm usage of pySerial.

The direct import of Serial and serial_for_url is correct under the new structure. Ensure that the pyserial library is properly specified as a dependency in the jumpstarter_driver_pyserial package to avoid runtime errors.

packages/jumpstarter-testing/conftest.py (3)

1-2: Good use of pytest import for fixture definitions.
Importing pytest directly ensures proper access to fixture capabilities without side effects.


3-3: Pytester plugin usage is appropriate.
Enabling pytester plugin is beneficial if you are writing tests for your own pytest plugins or need advanced test sandboxing.


6-8: Fixture strategy is solid.
Declaring anyio_backend here ensures consistent test environment setup with the asyncio backend for asynchronous tests. Great approach for cross-file usage.

packages/jumpstarter-cli/jumpstarter_cli/__main__.py (3)

1-2: Helpful module-level docstring.
This docstring succinctly explains how to run Jumpstarter through the -m flag. It’s clear and user-friendly.


3-3: Local import for CLI entry function is clear.
Importing jmp from the same package clarifies the module's responsibility and keeps the CLI structure modular.


5-6: Main entry point is properly guarded.
The if __name__ == "__main__": pattern is standard and ensures direct script execution triggers the CLI function. Passing prog_name="jmp" is a nice, concise name for commands.

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

1-4: Clear, explicit imports for adapter classes.
Grouping adapters in this __init__.py effectively communicates their availability and helps in discoverability. No issues detected.


6-6: Well-defined __all__ improves documentation and encapsulation.
By specifying __all__, you clarify which classes are public and make the package neatly exportable. This is a best practice for maintainable APIs.

packages/jumpstarter-cli-common/jumpstarter_cli_common/__init__.py (2)

5-5: Importing version utilities here improves discoverability.
Allowing version and get_client_version at a top-level import is beneficial for consistent version checks.


15-16: Expanded __all__ acknowledges new public items.
Explicitly including version and get_client_version clarifies this module’s public API. The approach is clean and straightforward.

packages/jumpstarter-cli/jumpstarter_cli/cli_test.py (3)

1-2: Imports look good.
No issues found with the pytest and asyncclick.testing imports.


17-19: Fixture usage confirmed.
The anyio_backend fixture is correctly defined and helps ensure the test runs under asyncio. This is good practice.


4-4: Confirm the relative import.
Ensure that jmp is defined in __init__.py within the same package. If so, this is perfectly fine.

✅ Verification successful

Relative import is correctly implemented
The jmp function is properly defined in __init__.py within the same package, making this relative import perfectly valid.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify jmp is correctly exported in the same directory (__init__.py).
rg -A 5 $'def jmp()'

Length of output: 432

packages/jumpstarter-cli/jumpstarter_cli/__init__.py (4)

1-5: Imports are well-organized.
All commands (admin, client, exporter, version) are brought in from their respective packages, keeping the CLI modular. Nice approach!


8-11: CLI group docstring is concise and clear.
The docstring succinctly describes the purpose of this CLI entry point. No issues here.


13-16: Command registration approach is appropriate.
Attaching each command to the jmp group is clean and keeps the CLI flexible. Nicely done.


18-19: Entry point logic is straightforward.
Invoking jmp() in the __main__ guard is correct. This ensures your CLI runs when invoked as a script.

packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver_test.py (1)

2-4: Newly updated imports.
Switching to the jumpstarter_driver_power import and relative Composite import are aligned with the new package structure. Looks good.

packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver_test.py (1)

4-4: Import of SDWire is aligned with the new structure.
No issues identified. Confirm that SDWire is properly defined in jumpstarter_driver_sdwire.driver.

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py (3)

4-8: Consider verifying module existence before referencing.
Ensure each imported module (.create, .delete, .get, .import_res, .install) exists and is properly packaged, since reorganizing the package layout can introduce circular dependencies or missing modules if not carefully managed.


11-14: CLI help string is concise and clear.
The docstring effectively communicates the CLI tool's purpose. Thank you for providing direct context to users.


16-21: Great use of subcommands.
By grouping logic under separate command files and adding them here, you effectively keep the CLI extensible and maintainable.

packages/jumpstarter-cli-common/jumpstarter_cli_common/opt.py (1)

15-17: Namespace usage is consistent.
Setting the default namespace to "default" aligns well with typical Kubernetes usage and standard best practices.

packages/jumpstarter/jumpstarter/config/__init__.py (1)

23-23: Ensure backward compatibility.
Exposing ExporterConfigV1Alpha1DriverInstance in __all__ changes the module's public API. Verify that it doesn't break existing imports or cause name collisions. Otherwise, looks good for the refactor.

packages/jumpstarter-testing/jumpstarter_testing/pytest_test.py (2)

3-3: Updated import path is consistent with the new driver location.
This change aligns with the reorganized driver packages. Good job ensuring references are updated.


7-7: Enforce consistent type hints.
Nice addition of the Pytester type annotation. Verify other test files and methods also use type hints, maintaining a consistent style throughout the codebase.

packages/jumpstarter/jumpstarter/common/condition.py (1)

3-3: Confirm consistent imports across the codebase.

The updated import path looks correct based on the reorganization. However, please verify all references are updated consistently and that no code still references the old path.

✅ Verification successful

Import paths are consistently updated

All references to kubernetes_pb2 are correctly imported from jumpstarter_protocol across the codebase. No instances of the old import path remain.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify that no references to the old import path remain.
rg "from jumpstarter\.v1 import kubernetes_pb2" -A 3 -B 3

Length of output: 59


Script:

#!/bin/bash
# Search for all kubernetes_pb2 imports
echo "=== Searching for kubernetes_pb2 imports ==="
rg "import.*kubernetes_pb2" -A 1 -B 1

echo -e "\n=== Searching for kubernetes_pb2 usage ==="
rg "kubernetes_pb2\." -A 1 -B 1

Length of output: 3125

packages/jumpstarter-cli-client/jumpstarter_cli_client/__init__.py (3)

1-7: Imports look appropriate.

These imports align well with the newly modularized structure. Good to see references split among their respective modules.


20-27: Effective grouping of subcommands.

Registering each subcommand individually is clear and well-organized. No issues found.


28-29: Dual invocation approach.

If you rely on if __name__ == "__main__": client(), confirm that j() is still needed or remove to prevent confusion. Otherwise, document why both exist.

packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/__init__.py (5)

1-2: Maintain consistent typing for log level.

Using Optional[str] is clear. This matches Python's type hinting style.


7-8: Organized subcommand imports.

Good job splitting logic to separate files (exporter.py, exporter_config.py), making it easier to maintain.


21-27: Straightforward command registration.

Clear approach to grouping exporter subcommands under a single CLI entry point.


29-30: Consistent script entry.

Matches the approach seen in other CLI packages. No issues.


4-5: Imports appear correct given the restructured modules.

No immediate issues, but verify each import path remains consistent with newly established naming conventions.

✅ Verification successful

Import paths are consistent with codebase conventions

The imports follow the established snake_case naming pattern used consistently across all packages in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify references to jumpstarter_cli_common remain consistent.
rg "jumpstarter_cli_common" -A 2 -B 2

Length of output: 6244

packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver_test.py (1)

4-4: Confirm proper import path and usage.

The reference to PexpectAdapter has been updated to the new jumpstarter_driver_network.adapters location. Ensure any remaining references to jumpstarter.client.adapters are removed or updated for consistency.

Below is a script to confirm no stale imports remain:

✅ Verification successful

Import path migration is complete and consistent

The codebase shows consistent usage of PexpectAdapter from jumpstarter_driver_network.adapters with no remaining references to the old import path.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searches for old import references in the codebase
rg "from jumpstarter\.client\.adapters import PexpectAdapter" -A 3 -B 3

Length of output: 73


Script:

#!/bin/bash
# Search for any variations of old imports
rg -i "jumpstarter\.client\.adapters.*PexpectAdapter"

# Search for any mentions of PexpectAdapter to verify consistent usage
rg "PexpectAdapter"

# Search for new import path to verify consistency
rg "from jumpstarter_driver_network\.adapters import.*PexpectAdapter"

# Use ast-grep to find import statements containing PexpectAdapter
ast-grep --pattern 'import $_PexpectAdapter'

Length of output: 2454

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

9-10: Local imports align with new structure.

The relative imports for TcpNetwork and NovncAdapter appear consistent with the reorganization approach. This enhances modularity.


7-7: Validate WebSocket dependency installation.

Including from websocket import create_connection requires a compatible websocket-client library version. Verify that websocket-client is listed in the relevant package's dependencies to prevent runtime import errors.

✅ Verification successful

WebSocket dependency is properly configured

The websocket-client package (version >=1.8.0) is correctly listed in the package's dependencies within pyproject.toml and properly locked in uv.lock.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Checks for the 'websocket-client' dependency in pyproject.toml or setup.py
rg "websocket-client"

Length of output: 288

packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (3)

12-12: Client path reference updated.

Returning a fully qualified path string to "jumpstarter_driver_power.client.PowerClient" correctly aligns with the new package naming.


49-49: Confirm the shift to sync generator for read().

Previously, a function returning an AsyncGenerator was replaced with a synchronous Generator. Ensure that callers of SyncMockPower.read() do not rely on async iteration.

✅ Verification successful

The sync generator change for SyncMockPower.read() is correctly implemented and used.

The codebase correctly handles the synchronous generator:

  • Test files properly use synchronous iteration with list(client.read())
  • No production code relies on async iteration for SyncMockPower
  • Both sync and async patterns are properly tested
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Look for code that might incorrectly await on SyncMockPower.read()
rg "await sync_mock_power\.read"

Length of output: 34


Script:

#!/bin/bash
# Find SyncMockPower class definition and usages
echo "=== Looking for SyncMockPower class ==="
rg "class SyncMockPower" -A 5

echo -e "\n=== Looking for SyncMockPower imports and instantiations ==="
rg "SyncMockPower"

echo -e "\n=== Looking for any async iteration or read() calls in test files ==="
rg "async for|\.read\(\)" $(fd -e test.py)

Length of output: 4951


2-2: Synchronous generator import looks intentional.

Adding Generator from collections.abc is consistent with a synchronous iteration approach. Confirm that upstream consumers don’t expect asynchronous behavior for these classes.

packages/jumpstarter-cli-client/jumpstarter_cli_client/lease.py (1)

6-6: Absolute import for AliasedGroup confirms stable namespace.

Changing the import to from jumpstarter_cli_common standardizes the CLI structure. Verify that jumpstarter_cli_common remains installed in all relevant environments.

✅ Verification successful

Import verification successful - jumpstarter_cli_common is properly installed and stable

The package is correctly declared in package configuration and consistently imported across all CLI packages, confirming a stable and standardized structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for references and ensure it's declared in setup configuration
rg "jumpstarter_cli_common"

Length of output: 1513

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

5-5: Relative Imports Aligned with New Package Structure
Switching to relative imports for TcpNetwork and FabricAdapter is consistent with the reorganized monorepo layout. Ensure you maintain consistency across the codebase, and be mindful of potential import issues if these modules are run directly as scripts.

Also applies to: 9-10

packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_test.py (6)

5-5: Consistent Import Style
Using a relative import (from . import exporter) streamlines maintenance within the package. This looks good.


18-20: Command Renamed to “create-config”
Renaming “create” to “create-config” increases clarity that the command relates to configuration creation. This aligns with your new CLI approach.


24-26: Duplicate Creation Handling
Same rename comment applies here. Also, good job verifying the creation command fails for duplicates.


34-34: Renaming “list” to “list-configs”
Renaming “list” to “list-configs” clarifies command behavior, especially in a multi-command setting. Looks consistent.


40-40: Renaming “delete” to “delete-config”
Uniformly differentiating commands for config-based operations is a solid approach. This rename follows the same pattern as “create-config.”


44-44: Verifying Deletion via “list-configs”
Double-checking exported configs after deletion is a good practice to ensure correctness. The usage of updated commands is consistent.

packages/jumpstarter-driver-dutlink/examples/dutlink.py (1)

7-7: Ensure consistency of PexpectAdapter import path
The new import path from jumpstarter_driver_network.adapters aligns with the reorganized driver structure. Confirm that there are no remaining references to the old path throughout the codebase.

✅ Verification successful

Import path for PexpectAdapter is consistent across the codebase
All references to PexpectAdapter consistently use the new import path jumpstarter_driver_network.adapters. No instances of the old import path were found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Checking references to the old import path 'jumpstarter.client.adapters' across the packages directory
rg 'from jumpstarter\.client\.adapters' packages/

Length of output: 320


Script:

#!/bin/bash
# Check for any references to PexpectAdapter with both old and new import paths
echo "=== Checking old import path ==="
rg "from jumpstarter\.client\.adapters.*PexpectAdapter" packages/

echo -e "\n=== Checking new import path ==="
rg "from jumpstarter_driver_network\.adapters.*PexpectAdapter" packages/

echo -e "\n=== Checking any other PexpectAdapter references ==="
rg "PexpectAdapter" packages/

Length of output: 2311

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

21-21: Confirm driver reference alignment
Returning "jumpstarter_driver_network.client.NetworkClient" is consistent with the new module structure. Verify that externally calling code referencing the old path is updated.

✅ Verification successful

No outdated references found
The codebase has been properly updated to use the new module structure. The only references to "jumpstarter.drivers" are in configuration tests and documentation, which are valid use cases unrelated to the network client implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching references to the old 'jumpstarter.drivers.network.client.NetworkClient'
rg 'jumpstarter\.drivers\.network\.client\.NetworkClient' packages/

Length of output: 69


Script:

#!/bin/bash
# Search for various potential references to the old network client
echo "=== Searching for old path patterns ==="
rg -i "jumpstarter\.drivers\.network" packages/

echo -e "\n=== Searching for import statements with NetworkClient ==="
ast-grep --pattern 'from $_ import NetworkClient'

echo -e "\n=== Searching for string references to NetworkClient ==="
rg "NetworkClient" packages/

echo -e "\n=== Checking for any jumpstarter.drivers references ==="
rg "jumpstarter\.drivers" packages/

Length of output: 2984

packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/adapter.py (1)

7-7: Adapted import for ClientAdapter
This matches the consolidated adapter pattern. Confirm no remnants of a local ClientAdapter remain.

✅ Verification successful

Verified: No local ClientAdapter remnants found
The codebase correctly uses the imported ClientAdapter from the consolidated location, with proper inheritance in OpendalAdapter and no remnants of any local implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching for leftover definitions or references to any locally defined 'ClientAdapter' in jumpstarter_driver_opendal
rg 'class ClientAdapter|ClientAdapter\(' packages/jumpstarter-driver-opendal

Length of output: 78


Script:

#!/bin/bash
# Broader search for any ClientAdapter references
echo "=== Searching for any ClientAdapter mentions ==="
rg -i "clientadapter" packages/jumpstarter-driver-opendal

echo -e "\n=== Looking for potential adapter files ==="
fd "adapter" packages/jumpstarter-driver-opendal

echo -e "\n=== Checking import statements ==="
rg "^from.*import.*ClientAdapter|^import.*ClientAdapter" packages/jumpstarter-driver-opendal

Length of output: 937

packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter.py (3)

5-7: Validate imports from internal modules.
Please confirm that jumpstarter.common.utils and jumpstarter.config.exporter are properly updated to reflect the new package structure introduced by this PR.


16-25: Gracefully handle partial failures.
The except* clause is helpful for grouping exceptions, but consider logging or handling partial states if the exporter completed some tasks before failing.


44-59: Check potential concurrency issues with config.serve_unix().
Ensure that only one exporter can bind to the same Unix socket if multiple shells run concurrently.

packages/jumpstarter-cli-client/jumpstarter_cli_client/client_test.py (6)

20-21: Confirm that “create-config” command is documented.
Please ensure user-facing docs or help text reflect this renamed command.


41-41: List command test coverage is good.
The assertions check both default and non-default clients in the output. This is comprehensive.


47-47: Check for potential concurrency in “use-config” command.
Parallel test runs or concurrent usage might cause race conditions if multiple tests try to set the same default config.


51-51: No issues found.
Implementation is consistent with the rename from “list” to “list-configs”.


57-57: Deleting default client is handled gracefully.
Well done verifying the exit code.


61-61: Check final outcome.
The assertion confirms removal of “test2” from the listing. This looks correct.

packages/jumpstarter-testing/jumpstarter_testing/pytest.py (4)

1-3: Logging setup is straightforward.
No issues found; minimal overhead.


5-9: Ensure dependency references are consistent.
jumpstarter.common and jumpstarter.config references might have changed with the new package structure; confirm paths are correct.


13-49: Docstring thoroughly explains usage.
This is excellent documentation for anyone extending JumpstarterTest.


53-65: Validate fallback logic.
Catching RuntimeError and loading a default client is good. Ensure that the fallback handles partial initialization states.

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py (1)

4-5: Validate newly imported modules.
Confirm jumpstarter_cli_common and jumpstarter_kubernetes references are correct and accessible after reorganizing packages.

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

10-12: Use of relative imports is aligned with the reorganization.
Swapping from absolute imports to relative imports is consistent with the new monorepo structure and helps keep package references localized. This looks good.

packages/jumpstarter/jumpstarter/client/core.py (1)

25-25: Updated import path reflects the new protocol package.
Referencing jumpstarter_protocol instead of jumpstarter.v1 aligns with the PR's reorganized package structure and helps maintain a clear separation of protocol definitions.

examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py (2)

11-11: Migration to the new testing module looks good.
Replacing jumpstarter.testing.pytest with jumpstarter_testing.pytest is consistent with the reorganized testing structure.


9-9: Ensure all references to the old adapter import are updated.
Shifting to jumpstarter_driver_network.adapters is correct for the new driver architecture. Verify no stray imports remain referencing the outdated path.

packages/jumpstarter/jumpstarter/config/exporter.py (2)

13-13: Reinstating Pydantic imports is appropriate.
Restoring BaseModel and Field ensures proper validation and default handling for your configuration classes.


19-19: Confirm updated default driver type references.
Changing the default from "jumpstarter.drivers.composite.driver.Composite" to "jumpstarter_driver_composite.driver.Composite" appears consistent with the new driver structure. Ensure no legacy references remain.

✅ Verification successful

Driver type references are correctly updated

The migration from jumpstarter.drivers.composite.driver.Composite to jumpstarter_driver_composite.driver.Composite is complete and consistent across the codebase. No legacy references remain, and all components properly use the new structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for occurrences of the old composite path in the codebase
rg "jumpstarter\.drivers\.composite\.driver\.Composite"

Length of output: 57


Script:

#!/bin/bash
# Search for any composite driver references
rg -i "composite.*driver" -A 2 -B 2

# Search specifically for the new path
rg "jumpstarter_driver_composite\.driver\.Composite"

# Find and check configuration files
fd -e yaml -e yml -e json -e toml -e ini -e cfg -e conf --exec grep -l "composite" {} \;

Length of output: 6961

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res_test.py (2)

11-11: Use of updated import path is well-aligned with the reorganized structure.
No issues detected. The switch to jumpstarter_kubernetes is consistent with the overall refactoring effort.


97-97: Refined test function signature looks clean and maintains clarity.
No gaps identified. The updated parameters remain consistent and typed.

packages/jumpstarter-cli-client/jumpstarter_cli_client/client_config.py (6)

1-2: Typings import is clear and minimal.
No concerns. This maintains Pythonic readability and hints for optional types.


3-6: Imports for asyncclick and make_table are straightforward.
No issues found with the usage or references.


8-65: Comprehensive client creation command with robust user prompts.
The logic to check for existing configs, prompt for inputs, and store the new config is clear. Error handling on duplicates is adequate.


83-89: Client config deletion mechanism is well-defined.
Logic to call set_next_client and remove the config is consistent.


91-114: Listing of client configs is neatly formatted.
Use of make_table in combination with star-marking the current config offers a clear UX.


115-120: Command for selecting the current config is straightforward.
Integration with UserConfigV1Alpha1.load_or_create() ensures a smooth fallback scenario.

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py (2)

6-6: Import statements are cleanly reorganized.
Switching to jumpstarter_kubernetes clarifies the dependency boundaries in this admin CLI module.

Also applies to: 13-15


17-20: Exception handling import from .k8s is well-defined.
Centralizing Kubernetes API handling fosters consistent error reporting across commands.

packages/jumpstarter/jumpstarter/client/lease.py (3)

14-14: Updated import path reflects the new proto package location.
Adopting jumpstarter_protocol is consistent with the reorganization approach.


55-55: Method docstring retains clarity.
Coordinates well with the asynchronous flow for requesting leases.


70-70: Docstring is properly descriptive of the lease acquisition process.
No corrections needed. It clearly outlines waiting, unsatisfiable, or release conditions.

packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver.py (11)

12-12: Import usage looks appropriate
No issues found with bringing in TftpServer from a local submodule. The dependency structure looks fine.


17-17: No tangible changes here
This is just an empty line, presumably for readability or linting.


28-28: Whitespace change
No functional impact.


31-31: No modifications needed
This pass statement in TftpError is acceptable.


34-37: New custom exception class
Defining ServerNotRunning as a subclass of TftpError fits well to handle server availability issues.


40-43: New custom exception class
FileNotFound specifically clarifies missing file scenarios instead of using a generic error, which is helpful.


54-54: Improved type referencing
Using server: Optional["TftpServer"] clarifies the driver’s server attribute without circular imports.


Line range hint 61-61: Loop readiness signaling
Calling self._loop_ready.set() ensures calling threads can synchronize on event loop availability. Looks correct.


Line range hint 76-76: Method definition
The _run_server coroutine structure with clear exception handling is suitable for an async TFTP server.


93-93: Concurrent tasks
Using asyncio.gather(server_task, self._wait_for_shutdown()) is a clean way to run the server until shutdown. Good job handling potential cancellations.


103-103: Proper resource cleanup
The await self.server.shutdown() call is guarded by a server is not None check, which prevents errors on shutdown. Nicely done.

packages/jumpstarter-driver-can/jumpstarter_driver_can/client.py (1)

12-12: Reinstating Pydantic validation
Reintroducing validate_call and ConfigDict ensures strong data validation for CAN operations.

packages/jumpstarter/jumpstarter/config/client.py (5)

11-12: Refined import paths
Switching to jumpstarter_protocol for jumpstarter_pb2 and jumpstarter_pb2_grpc unifies protocol references across the repo. Importing Pydantic is consistent with your data modeling approach.


29-29: Dedicated config model
ClientConfigV1Alpha1Drivers neatly encapsulates the allow and unsafe fields, aligning with environment-based logic.


61-61: Blocking portal usage
Wrapping the async lease context with portal.wrap_async_context_manager helps unify blocking and async flows. No issues found.


76-76: Async lease request
Ensuring async context usage for requesting a lease is a clean approach for resource management.


79-79: Deferred import for circular dependency avoidance
Importing Lease inside the method avoids potential circular references. Good solution.

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py (3)

5-14: Import reorganization
Centralizing shared CLI utilities under jumpstarter_cli_common and referencing jumpstarter_kubernetes is consistent with the new monorepo structure.


22-23: Aligning exception imports
Importing ApiException and ConfigException from kubernetes_asyncio clarifies your Kubernetes error handling path.


25-25: Local K8s utilities
handle_k8s_api_exception and handle_k8s_config_exception are cleanly separated in .k8s for error management.

packages/jumpstarter-driver-can/jumpstarter_driver_can/client_test.py (1)

10-10: No conflicts with the updated import paths.

The newly imported classes from jumpstarter_driver_can are utilized consistently throughout the tests and align with the reorganized driver structure. Nicely done updating references to maintain test coverage.

packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (1)

15-18: Imports align with the new module structure.

These new import paths match the reorganized driver packages. No issues detected in usage or naming.

.github/workflows/ruff.yaml (1)

20-22: Transition to the updated Ruff GitHub Action.

Switching to astral-sh/ruff-action@v3 and introducing the version-file parameter is a solid improvement. Please ensure that CI logs confirm a smooth transition.

.pre-commit-config.yaml (1)

1-1: LGTM! The pre-commit configuration looks good.

The change to use pre-commit stage is more standard and aligns better with typical pre-commit hook execution patterns.

examples/soc-pytest/pyproject.toml (1)

14-19: LGTM! Dependencies updated to follow new package naming convention.

The changes align well with the PR objective of standardizing package naming and improving modularity.

Verify version compatibility across packages.

Please ensure that the specified versions of all packages are compatible with each other, especially for the newly added dependencies.

Run this script to check version compatibility:

✅ Verification successful

Dependencies are compatible within the internal package ecosystem

The packages are part of an internal ecosystem using dynamic versioning, and the pytest requirement (>=8.3.2) is satisfied by the latest version (8.3.4). No version conflicts detected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check version compatibility across packages

# Get the latest versions of all packages from PyPI
for pkg in pytest jumpstarter-testing jumpstarter-imagehash jumpstarter-driver-network jumpstarter-driver-dutlink; do
  echo "Checking $pkg..."
  curl -s "https://pypi.org/pypi/$pkg/json" | jq -r '.info.version'
done

# Check if packages exist in the workspace
fd -t f "pyproject.toml" packages/ -x cat {} \; | grep -A1 "name = "

Length of output: 5710

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

30-30: LGTM! VCS root path updated correctly.

The update to the VCS root path aligns with the new package structure in the packages/ directory.


13-14: Verify the impact of dependency changes.

The removal of hardware-specific dependencies (pyudev, pyusb) and addition of new dependencies (asyncclick, jumpstarter-driver-power) suggests significant changes in functionality.

Run this script to analyze the impact:

Also applies to: 20-21

✅ Verification successful

Dependencies properly migrated and integrated

The codebase shows clean removal of hardware-specific dependencies and proper integration of new ones:

  • asyncclick is correctly imported and used for CLI implementation in client.py
  • jumpstarter-driver-power integration is present in tests
  • No remnants of removed hardware dependencies (pyudev, pyusb) found
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining hardware-specific code and new CLI usage

# Look for any remaining hardware-specific imports or usage
rg -l "usb|udev" packages/jumpstarter-driver-composite/

# Check for CLI implementation using asyncclick
ast-grep --pattern 'import asyncclick' -l

Length of output: 207


Script:

#!/bin/bash
# First, verify the package structure
fd . packages/jumpstarter-driver-composite/ -t f -e py

# Check for hardware-specific imports and usage
rg -t py "(?:import|from)\s+(?:pyusb|pyudev)" packages/jumpstarter-driver-composite/
rg -t py "(?:usb|udev)" packages/jumpstarter-driver-composite/

# Check for new dependency usage
rg -t py "(?:import|from)\s+(?:asyncclick|jumpstarter_driver_power)" packages/jumpstarter-driver-composite/
rg -t py "@(?:asyncclick|click)\." packages/jumpstarter-driver-composite/

# Look for CLI implementation
ast-grep --pattern 'import asyncclick' --lang python
ast-grep --pattern 'from asyncclick import' --lang python

Length of output: 1507

packages/jumpstarter-imagehash/pyproject.toml (1)

30-30: LGTM! VCS root path updated correctly.

The update to the VCS root path aligns with the new package structure in the packages/ directory.

packages/jumpstarter-testing/pyproject.toml (1)

9-15: LGTM! The testing package setup looks good.

The creation of a dedicated testing package with appropriate dependencies aligns well with the PR objective of better modularity.

Makefile (2)

1-1: LGTM! Package targets now use the new directory structure.

The change from contrib/drivers and contrib/libs to packages/* aligns with the PR's objective of reorganizing packages into a dedicated directory.


16-19: LGTM! Test targets have been consolidated.

The unified test target structure simplifies testing across all packages while maintaining isolation through uv run --isolated.

__templates__/create_driver.sh (2)

24-26: LGTM! Directory structure aligns with new package organization.

The change to use packages/jumpstarter_driver_${DRIVER_NAME} follows the new standardized package naming convention and directory structure.


38-38: Verify template path consistency.

The template path has been updated to packages/__templates__/driver/, but the script still uses contrib/__templates__/driver/jumpstarter_driver/ on line 33.

packages/jumpstarter-driver-http/jumpstarter_driver_http/driver.py (2)

50-54: LGTM! Improved route configuration readability.

The multi-line format for route configuration improves readability and makes future route additions more maintainable.


133-133: LGTM! Consistent formatting improvements.

Minor formatting improvements:

  • Consistent use of double quotes for string literals
  • Added whitespace for better readability

Also applies to: 174-174

@@ -14,7 +14,7 @@ dependencies = [

[tool.hatch.version]
source = "vcs"
raw-options = { 'root' = '../../../'}
raw-options = { 'root' = '../../'}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

The relative path in raw-options needs to be ../../../ to correctly reference the repository root

Based on the file location at git/__templates__/driver/pyproject.toml.tmpl, two levels of ../ would only reach the git/ directory. To properly reference the repository root, three levels (../../../) are required.

🔗 Analysis chain

Confirm the relative path for version control is still valid.

Previously, the raw-options path was set to ../../../, and now it's changed to ../../. Ensure this adjustment correctly references the repository root under the new directory structure. Once satisfied, feel free to resolve this comment.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the updated 'raw-options' path is correct relative to this template file.

# Because the new directory layout was restructured, confirm the repository's layout
# usage by listing the directory tree for each driver or by analyzing the location
# of each pyproject.toml.tmpl file. 
# The following command shows all driver pyproject templates and their directory paths:
fd pyproject.toml.tmpl -t f

Length of output: 74

Comment on lines +37 to 39
"pytest-asyncio>=0.0.0",
"ruff>=0.7.1",
"pytest-asyncio>=0.24.0",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate pytest-asyncio dependency with redundant version constraint.

The dev dependencies list contains two entries for pytest-asyncio with different version constraints:

  • pytest-asyncio>=0.0.0 (redundant as it effectively means no constraint)
  • pytest-asyncio>=0.24.0 (actual constraint)

Apply this diff to remove the redundant dependency:

 dev = [
     "pytest-cov>=6.0.0",
     "pytest>=8.3.3",
-    "pytest-asyncio>=0.0.0",
     "ruff>=0.7.1",
     "pytest-asyncio>=0.24.0",
 ]
📝 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.

Suggested change
"pytest-asyncio>=0.0.0",
"ruff>=0.7.1",
"pytest-asyncio>=0.24.0",
"ruff>=0.7.1",
"pytest-asyncio>=0.24.0",

Comment on lines +5 to +6
from jumpstarter_driver_network.adapters import PexpectAdapter
from pexpect.fdpexpect import fdspawn
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Import paths need to be standardized across the codebase

The following files still use the old import path jumpstarter.client.adapters and need to be updated:

  • packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/adapter.py
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/portforward.py
  • docs/source/api-reference/adapters.md
🔗 Analysis chain

Validate updated import statements.

Great job updating the import path for PexpectAdapter. Please ensure that the renamed adapter package is consistently referenced throughout the codebase to avoid import errors.

Use a script to confirm that all references to jumpstarter.client.adapters have been removed or replaced:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
rg 'jumpstarter\.client\.adapters'

Length of output: 387


Script:

#!/bin/bash
# Check for partial matches and specific adapter imports
echo "=== Checking for partial matches of old import path ==="
rg -i 'jumpstarter.*adapters'

echo -e "\n=== Checking for specific adapter imports ==="
rg -i 'from jumpstarter.*import.*[Aa]dapter'

echo -e "\n=== Checking for new import path usage ==="
rg 'jumpstarter_driver_network\.adapters'

Length of output: 2913

@@ -41,7 +40,7 @@ def __post_init__(self):

@classmethod
def client(cls) -> str:
return "jumpstarter.drivers.pyserial.client.PySerialClient"
return "jumpstarter_driver_pyserial.client.PySerialClient"
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Update PySerialClient path in API documentation

The client path needs to be updated in the following file:

  • docs/source/api-reference/drivers/pyserial.md: Update jumpstarter.drivers.pyserial.client.PySerialClient to jumpstarter_driver_pyserial.client.PySerialClient
🔗 Analysis chain

Check updated return path for the client.

The client path now references jumpstarter_driver_pyserial.client.PySerialClient. Make sure there are no remaining references to the old path in YAML files or user documentation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
rg 'jumpstarter\.drivers\.pyserial\.client\.PySerialClient'

Length of output: 173


Script:

#!/bin/bash
# Search for YAML files with pyserial references
echo "=== Searching YAML files ==="
rg -t yaml 'pyserial'

# Search for documentation files with pyserial client references
echo -e "\n=== Searching documentation files ==="
fd -e md -e rst -e txt . | xargs rg -l 'PySerialClient'

# Search for any other variations of the path
echo -e "\n=== Searching for path variations ==="
rg 'PySerialClient' -g '!*.py'

Length of output: 695

@@ -4,7 +4,7 @@ endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
token: "<token>"
export:
serial:
type: "jumpstarter.drivers.pyserial.driver.PySerial"
type: "jumpstarter_driver_pyserial.driver.PySerial"
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Documentation needs to be updated to match the new driver type reference

The old format "jumpstarter.drivers.pyserial.driver.PySerial" is still present in documentation files and should be updated to "jumpstarter_driver_pyserial.driver.PySerial" for consistency:

  • docs/source/config.md
  • docs/source/api-reference/drivers/pyserial.md (2 occurrences)
🔗 Analysis chain

Confirm updated driver type reference.

The type field is updated to "jumpstarter_driver_pyserial.driver.PySerial". Verify that further references of "jumpstarter.drivers.pyserial.driver.PySerial" have been removed or replaced to maintain consistency.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
rg 'jumpstarter\.drivers\.pyserial\.driver\.PySerial'

Length of output: 342

Comment on lines +10 to +22
"create": ["c"],
"import": ["i"],
"get": ["g"],
"admin": ["a"],
"create-config": ["cc"],
"delete-config": ["dc"],
"edit-config": ["ec"],
"list-configs": ["lc"],
"use-config": ["uc"],
"move": ["mv"],
"config": ["conf"],
"delete": ["del"],
"shell": ["sh"],
"delete": ["del", "d"],
"shell": ["sh", "s"],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential Alias Collision for "c"
Defining both "create": ["c"] and "client": ["clients", "c"] in common_aliases raises a collision for the alias "c". This would trigger the Too many matches error when typing c on the CLI.

Below is a sample diff removing "c" from the client alias list:

 "client": ["clients", "c"],
 "create": ["c"],
 ...
-"client": ["clients", "c"]
+"client": ["clients"]

Also applies to: 26-26

@@ -151,6 +152,7 @@ async def get_exporter(

LEASE_COLUMNS = ["NAME", "CLIENT", "SELECTOR", "EXPORTER", "STATUS", "REASON", "BEGIN", "END", "DURATION", "AGE"]


Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential missing return path
In get_reason, if reason is neither "Ready" nor "Expired", the function does not return a value, leading to an implicit None. Consider adding a default return case to handle unknown reasons.

Here's a possible fix to return the original reason if it's an unexpected type:

 def get_reason(lease: V1Alpha1Lease):
     condition = lease.status.conditions[-1] if len(lease.status.conditions) > 0 else None
     reason = condition.reason if condition is not None else "Unknown"
     status = condition.status if condition is not None else "False"
     if reason == "Ready":
         if status == "True":
             return "Ready"
         else:
             return "Waiting"
     elif reason == "Expired":
         if status == "True":
             return "Expired"
         else:
             return "Complete"
+    else:
+        return reason

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +6 to +8
out: ./packages/jumpstarter_protocol/jumpstarter_protocol
- remote: buf.build/grpc/python
out: .
out: ./packages/jumpstarter_protocol/jumpstarter_protocol
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Path mismatch detected in buf.gen.yaml configuration

The output path in buf.gen.yaml uses jumpstarter_protocol (with underscore) but the actual directory uses jumpstarter-protocol (with hyphen). This mismatch should be corrected to ensure proper file generation.

  • Update the output paths in buf.gen.yaml to use ./packages/jumpstarter-protocol/jumpstarter_protocol
🔗 Analysis chain

Verify that the new output paths are correct.

The updated paths in buf.gen.yaml look appropriate. Please confirm that the generated files appear under ./packages/jumpstarter_protocol/jumpstarter_protocol as intended.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# This script verifies that the directory for generated code is present
fd "jumpstarter_protocol" --hidden --no-ignore

Length of output: 98

@@ -1,25 +1,24 @@
[project]
name = "jumpstarter-driver-dutlink"
name = "jumpstarter-driver-composite"
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Documentation needed for the composite driver architecture

The code review reveals that the rename to "composite" is technically justified as the package implements the Composite design pattern, allowing hierarchical composition of multiple drivers (as demonstrated in driver_test.py). However, this significant architectural pattern needs proper documentation:

  • Add design rationale and usage examples to README.md
  • Include docstrings in driver.py and client.py explaining the composite pattern implementation
  • Document how to compose and configure nested drivers
🔗 Analysis chain

Document the rationale for renaming the driver package.

The package has been renamed from jumpstarter-driver-dutlink to jumpstarter-driver-composite. Please add documentation explaining the purpose and functionality of this composite driver.

Run this script to check for documentation:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for documentation about the composite driver

# Look for README or documentation files
fd -t f "README.md|CHANGELOG.md" packages/jumpstarter-driver-composite/ -x cat {}

# Look for docstrings in Python files
rg -l "\"\"\"" packages/jumpstarter-driver-composite/src/

Length of output: 255


Script:

#!/bin/bash
# Check repository structure and find Python files
echo "Repository structure:"
fd . packages/jumpstarter-driver-composite/

echo -e "\nSearching for Python files:"
fd -e py . packages/jumpstarter-driver-composite/

echo -e "\nChecking file contents if found:"
fd -e py . packages/jumpstarter-driver-composite/ -x cat {}

Length of output: 2654

Comment on lines +12 to +14
"pytest-anyio>=0.0.0",
"pytest-asyncio>=0.0.0",
"pytest-cov>=5.0.0"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add version constraints for pytest plugins.

The pytest plugins are missing version constraints which could lead to compatibility issues.

Apply this diff to add version constraints:

-  "pytest-anyio>=0.0.0",
-  "pytest-asyncio>=0.0.0",
+  "pytest-anyio>=4.3.0",
+  "pytest-asyncio>=0.23.5",
📝 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.

Suggested change
"pytest-anyio>=0.0.0",
"pytest-asyncio>=0.0.0",
"pytest-cov>=5.0.0"
"pytest-anyio>=4.3.0",
"pytest-asyncio>=0.23.5",
"pytest-cov>=5.0.0"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reorganize jmp commands to the 0.6 proposal
2 participants