Skip to content

Conversation

@NickCao
Copy link
Collaborator

@NickCao NickCao commented Jan 16, 2026

Summary by CodeRabbit

  • New Features

    • SNMP driver now integrates with the power-control interface and uses asynchronous operations for improved responsiveness.
  • Chores

    • CI matrix extended to include Python 3.14 and adjusted test strategy.
    • Updated core dependencies: Pydantic, gRPC, Pillow, Zstandard.
  • Tests

    • Key SNMP tests migrated to async execution.
  • Documentation

    • README updated to reference the consolidated power client API.

✏️ Tip: You can customize this high-level summary in your review settings.

@netlify
Copy link

netlify bot commented Jan 16, 2026

Deploy Preview for jumpstarter-docs ready!

Name Link
🔨 Latest commit c2b88b5
🔍 Latest deploy log https://app.netlify.com/projects/jumpstarter-docs/deploys/696e9d21ece25e00087b6f70
😎 Deploy Preview https://deploy-preview-803--jumpstarter-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

Expanded CI Python matrix to include 3.14 and disabled fail-fast; bumped several package dependencies (pydantic, grpcio, zstandard, pillow); refactored SNMP driver to async PowerInterface (async on/off, anyio.Event, fail_after), removed SNMPServerClient CLI, and converted SNMP tests to async anyio.

Changes

Cohort / File(s) Summary
CI workflow
.github/workflows/pytest.yaml
Added strategy.fail-fast: false; extended matrix.python-version to include 3.14
Pydantic bumps
packages/jumpstarter-cli-common/pyproject.toml, packages/jumpstarter-kubernetes/pyproject.toml, packages/jumpstarter/pyproject.toml
Bumped pydantic constraint from >=2.8.2 to >=2.12.5
Other dependency upgrades
packages/jumpstarter-protocol/pyproject.toml, packages/jumpstarter-driver-uboot/pyproject.toml, packages/jumpstarter-driver-ustreamer/pyproject.toml
Upgraded grpcio (>=1.66.1 → >=1.76.0), zstandard (0.23.0 → 0.25.0), and pillow (>=10.4.0 → >=12.1.0)
SNMP driver core refactor
packages/jumpstarter-driver-snmp/.../driver.py
SNMPServer now implements PowerInterface; _snmp_set, on, off converted to async; switched from asyncio.Event to anyio.Event/Event; removed custom loop handling; added read() -> AsyncGenerator[PowerReading, None]; updated callbacks/dispatcher to Event/fail_after flow
SNMP CLI removal
packages/jumpstarter-driver-snmp/.../client.py
Removed SNMPServerClient methods on(), off(), and cli() (class reduced to dataclass/pass)
SNMP tests → async
packages/jumpstarter-driver-snmp/.../driver_test.py
Converted tests to async def with @pytest.mark.anyio; await on()/off(); removed asyncio event-loop patches
Docs update
packages/jumpstarter-driver-snmp/README.md
API reference updated to jumpstarter_driver_power.client.PowerClient() and added :no-index:

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Caller
    participant SNMPServer as SNMPServer
    participant SNMPEngine as SNMP Engine
    participant Event as anyio.Event

    Caller->>SNMPServer: await on()/off() -> calls _snmp_set
    SNMPServer->>SNMPEngine: send SNMP SET request
    SNMPEngine->>Event: callback signals response (response_received.set)
    SNMPServer->>Event: await response_received with fail_after timeout
    Event-->>SNMPServer: response received
    SNMPServer-->>Caller: return result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

backport release-0.7

Suggested reviewers

  • mangelajo
  • bennyz

Poem

🐰 I hopped from sync into the async glade,

Awaited events where callbacks played.
Clients trimmed, the engine hums light,
Dependencies bumped and Python takes flight,
A joyful hop into 3.14 tonight! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Simplify SNMP driver' accurately reflects the main change in the PR—removing unnecessary complexity from the SNMP driver implementation while maintaining core functionality.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1)

143-168: Ensure dispatcher is closed even when the await times out or is cancelled.

The await response_received.wait() can be cancelled by the fail_after timeout in the caller. Without try/finally, close_dispatcher() will be skipped, leaving the dispatcher open and leaking resources. Wrap the wait to guarantee cleanup.

✅ Safe dispatcher lifecycle
 async def _run_snmp_dispatcher(self, snmp_engine: engine.SnmpEngine, response_received: Event):
     snmp_engine.open_dispatcher()
-    await response_received.wait()
-    snmp_engine.close_dispatcher()
+    try:
+        await response_received.wait()
+    finally:
+        snmp_engine.close_dispatcher()
🤖 Fix all issues with AI agents
In `@packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py`:
- Around line 40-42: The class currently declared as SNMPServer (which
implements PowerInterface and Driver) should be renamed to end with "Power"
(e.g., SNMPPower or SNMPServerPower) and all references updated; change the
class name declaration from SNMPServer to the chosen new name and update any
imports, type annotations, factory registrations, tests, and usages that
reference SNMPServer (look for occurrences in jumpstarter_driver_snmp.driver,
any places constructing the driver, isinstance/type checks, and documentation
strings) so the symbol implementing PowerInterface now follows the "*Power"
naming convention.
- Around line 2-8: The SNMP driver imports anyio (Event, fail_after) but the
package manifest doesn't declare it; add anyio to the package's dependencies in
the pyproject.toml for the jumpstarter-driver-snmp package (e.g., under
[project] or tool.poetry.dependencies add "anyio" with an appropriate version
constraint), then update lock/install so runtime imports of Event and fail_after
from anyio succeed.

In `@packages/jumpstarter-driver-ustreamer/pyproject.toml`:
- Line 13: pyproject.toml is missing the required entry-point registration for
the driver; add a [project.entry-points."jumpstarter.drivers"] section and
register this package under that group using the module:class target for the
driver (follow the pattern used by jumpstarter-driver-can and
jumpstarter-driver-composite), e.g., add an entry like my_driver_name =
"jumpstarter_driver_ustreamer:UstreamerDriver" replacing
my_driver_name/module/class with the actual package module and driver class name
so jumpstarter can auto-discover the driver.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 595a7fa and 7dd9965.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .github/workflows/pytest.yaml
  • packages/jumpstarter-cli-common/pyproject.toml
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver_test.py
  • packages/jumpstarter-driver-uboot/pyproject.toml
  • packages/jumpstarter-driver-ustreamer/pyproject.toml
  • packages/jumpstarter-kubernetes/pyproject.toml
  • packages/jumpstarter-protocol/pyproject.toml
  • packages/jumpstarter/pyproject.toml
💤 Files with no reviewable changes (1)
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py
🧰 Additional context used
📓 Path-based instructions (6)
packages/jumpstarter-driver-*/pyproject.toml

📄 CodeRabbit inference engine (.cursor/rules/creating-new-drivers.mdc)

Driver package names should be lowercase with hyphens for multi-word names (e.g., my-driver, custom-power, device-controller)

packages/jumpstarter-driver-*/pyproject.toml: Driver packages must follow the naming pattern jumpstarter-driver-<name>
Driver packages must register via the jumpstarter.drivers entry point in pyproject.toml
Driver packages must depend on jumpstarter and specific hardware libraries in their pyproject.toml

Files:

  • packages/jumpstarter-driver-uboot/pyproject.toml
  • packages/jumpstarter-driver-ustreamer/pyproject.toml
packages/*/pyproject.toml

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Each package's pyproject.toml must include project metadata with Apache-2.0 license only

Files:

  • packages/jumpstarter-driver-uboot/pyproject.toml
  • packages/jumpstarter-protocol/pyproject.toml
  • packages/jumpstarter-kubernetes/pyproject.toml
  • packages/jumpstarter-driver-ustreamer/pyproject.toml
  • packages/jumpstarter-cli-common/pyproject.toml
  • packages/jumpstarter/pyproject.toml
packages/jumpstarter-driver-**/jumpstarter_driver_**/*.py

📄 CodeRabbit inference engine (.cursor/rules/creating-new-drivers.mdc)

Driver implementations should follow existing code style validated with make lint (fix with make lint-fix), perform static type checking with make ty-pkg-${package_name}, add comprehensive tests, and verify all tests pass with make test-pkg-${package_name} or make test

Files:

  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver_test.py
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Ruff should be used for code formatting and linting, excluding jumpstarter-protocol package

Files:

  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver_test.py
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py
packages/jumpstarter-cli-*/pyproject.toml

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

CLI packages must depend on jumpstarter and jumpstarter-cli-common in their pyproject.toml

Files:

  • packages/jumpstarter-cli-common/pyproject.toml
packages/jumpstarter-driver-*/jumpstarter_driver_*/driver.py

📄 CodeRabbit inference engine (.cursor/rules/creating-new-drivers.mdc)

Driver class names should be in CamelCase and be descriptive with appropriate suffixes based on functionality: Power drivers should end with *Power, Network drivers with *Network, Flasher drivers with *Flasher, Console drivers with *Console, Server drivers with *Server

Files:

  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py
🧠 Learnings (10)
📚 Learning: 2025-11-27T09:58:55.346Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-27T09:58:55.346Z
Learning: Applies to packages/jumpstarter-driver-*/pyproject.toml : Driver packages must depend on `jumpstarter` and specific hardware libraries in their `pyproject.toml`

Applied to files:

  • packages/jumpstarter-driver-uboot/pyproject.toml
  • packages/jumpstarter-protocol/pyproject.toml
  • packages/jumpstarter-kubernetes/pyproject.toml
  • packages/jumpstarter-driver-ustreamer/pyproject.toml
  • packages/jumpstarter-cli-common/pyproject.toml
  • packages/jumpstarter/pyproject.toml
📚 Learning: 2025-11-27T09:58:55.346Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-27T09:58:55.346Z
Learning: Applies to packages/jumpstarter-cli-*/pyproject.toml : CLI packages must depend on `jumpstarter` and `jumpstarter-cli-common` in their `pyproject.toml`

Applied to files:

  • packages/jumpstarter-driver-uboot/pyproject.toml
  • packages/jumpstarter-protocol/pyproject.toml
  • packages/jumpstarter-kubernetes/pyproject.toml
  • packages/jumpstarter-driver-ustreamer/pyproject.toml
  • packages/jumpstarter-cli-common/pyproject.toml
  • packages/jumpstarter/pyproject.toml
📚 Learning: 2025-11-27T09:58:55.346Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-27T09:58:55.346Z
Learning: Applies to packages/jumpstarter-driver-*/pyproject.toml : Driver packages must follow the naming pattern `jumpstarter-driver-<name>`

Applied to files:

  • packages/jumpstarter-driver-uboot/pyproject.toml
  • packages/jumpstarter-driver-ustreamer/pyproject.toml
  • packages/jumpstarter-cli-common/pyproject.toml
  • packages/jumpstarter/pyproject.toml
📚 Learning: 2025-11-27T09:58:55.346Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-27T09:58:55.346Z
Learning: Applies to packages/jumpstarter-driver-*/pyproject.toml : Driver packages must register via the `jumpstarter.drivers` entry point in `pyproject.toml`

Applied to files:

  • packages/jumpstarter-driver-uboot/pyproject.toml
  • packages/jumpstarter-protocol/pyproject.toml
  • packages/jumpstarter-driver-ustreamer/pyproject.toml
  • packages/jumpstarter-cli-common/pyproject.toml
  • packages/jumpstarter/pyproject.toml
📚 Learning: 2025-09-02T07:32:04.548Z
Learnt from: mangelajo
Repo: jumpstarter-dev/jumpstarter PR: 589
File: packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py:0-0
Timestamp: 2025-09-02T07:32:04.548Z
Learning: *_pb2.py files in the jumpstarter codebase are auto-generated from gRPC/protobuf definitions and should not be manually modified. Issues with these files should be addressed at the protobuf generation tooling level or runtime environment setup.

Applied to files:

  • packages/jumpstarter-protocol/pyproject.toml
📚 Learning: 2025-11-27T09:58:55.346Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-27T09:58:55.346Z
Learning: Core packages must depend on `jumpstarter-protocol`

Applied to files:

  • packages/jumpstarter-protocol/pyproject.toml
  • packages/jumpstarter-kubernetes/pyproject.toml
  • packages/jumpstarter-cli-common/pyproject.toml
📚 Learning: 2025-11-05T13:45:58.271Z
Learnt from: mangelajo
Repo: jumpstarter-dev/jumpstarter PR: 735
File: packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py:15-15
Timestamp: 2025-11-05T13:45:58.271Z
Learning: In packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py, pexpect is intentionally used as a transitive dependency through the jumpstarter-driver-pyserial package. The flashers package does not declare pexpect as a direct dependency because the pyserial driver package is intended to control the pexpect version.

Applied to files:

  • packages/jumpstarter-kubernetes/pyproject.toml
  • packages/jumpstarter-cli-common/pyproject.toml
📚 Learning: 2025-11-27T09:58:41.875Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/creating-new-drivers.mdc:0-0
Timestamp: 2025-11-27T09:58:41.875Z
Learning: Applies to packages/jumpstarter-driver-**/jumpstarter_driver_**/*.py : Driver implementations should follow existing code style validated with `make lint` (fix with `make lint-fix`), perform static type checking with `make ty-pkg-${package_name}`, add comprehensive tests, and verify all tests pass with `make test-pkg-${package_name}` or `make test`

Applied to files:

  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver_test.py
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py
📚 Learning: 2025-11-27T09:58:41.875Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/creating-new-drivers.mdc:0-0
Timestamp: 2025-11-27T09:58:41.875Z
Learning: Applies to packages/jumpstarter-driver-*/jumpstarter_driver_*/driver.py : Driver class names should be in CamelCase and be descriptive with appropriate suffixes based on functionality: Power drivers should end with `*Power`, Network drivers with `*Network`, Flasher drivers with `*Flasher`, Console drivers with `*Console`, Server drivers with `*Server`

Applied to files:

  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py
📚 Learning: 2025-11-27T09:58:55.346Z
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-27T09:58:55.346Z
Learning: Applies to packages/jumpstarter-driver-*/jumpstarter_driver_*/ : Driver packages must implement a `driver.py` file containing the driver implementation

Applied to files:

  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py
🧬 Code graph analysis (1)
packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver_test.py (1)
packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (2)
  • on (183-185)
  • off (188-190)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.14)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
  • GitHub Check: e2e
🔇 Additional comments (11)
packages/jumpstarter/pyproject.toml (1)

18-18: LGTM - consistent pydantic version bump.

The update aligns with the pydantic version in jumpstarter-cli-common. The package correctly depends on jumpstarter-protocol as required for core packages. The conditional backports-zstd dependency (line 23) confirms this PR's Python 3.14 support focus.

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

22-22: LGTM - zstandard dev dependency bump is valid.

zstandard 0.25.0 is a stable, non-yanked release compatible with the package's Python requirement. The change is confined to dev dependencies, limiting impact to development/testing. Package follows the required naming pattern jumpstarter-driver-<name> and correctly depends on jumpstarter and jumpstarter-driver-composite. Note: entry points registration is not present in the current file state but is pre-existing and not introduced by this change.

packages/jumpstarter-cli-common/pyproject.toml (1)

11-11: LGTM - pydantic dependency update.

File complies with coding guidelines: Apache-2.0 license, depends on jumpstarter. pydantic 2.12.5 is a valid release (requires Python >=3.9, compatible with the package's >=3.11 requirement).

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

11-11: LGTM - grpcio version bump to >=1.76.0.

The dependency update extends Python 3.14 support (grpcio 1.76.0 supports Python 3.9–3.14). Package metadata is compliant with Apache-2.0 license.

packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (2)

122-141: LGTM: callback still records errors and signals completion.


118-120: Verify SNMPServerClient existence and client.py implementation

Confirm whether SNMPServerClient exists in packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py. If the class was removed or renamed, update the client() method on line 120 to reference the correct class name, or remove this method if client support is no longer needed.

packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver_test.py (3)

58-103: LGTM: auth configuration assertions remain intact.


105-128: LGTM: power-on test still validates command dispatch.


131-154: LGTM: power-off test still validates command dispatch.

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

9-12: Verify the pydantic floor against the repo's Python matrix.

Pydantic 2.12.5 supports Python 3.11–3.14 (the 2.12 series added initial Python 3.14 support; Pydantic 2.x requires Python ≥ 3.9). Confirm this aligns with the repository's declared Python matrix and other package constraints.

.github/workflows/pytest.yaml (1)

18-21: Python 3.14 is available in both setup-uv and GitHub Actions runners. The astral-sh/setup-uv action supports Python 3.14 via the python-version input, and both ubuntu-24.04 and macos-15 include Python 3.14 in their hosted toolcache. No action needed.

Likely an incorrect or invalid review comment.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +2 to +8
from collections.abc import AsyncGenerator
from dataclasses import dataclass, field
from enum import Enum, IntEnum
from typing import Any, Dict, Tuple
from typing import Any, Dict

from anyio import Event, fail_after
from jumpstarter_driver_power.driver import PowerInterface, PowerReading
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether anyio is declared in SNMP driver's pyproject.toml
cat packages/jumpstarter-driver-snmp/pyproject.toml | grep -A 20 -B 5 dependencies

Repository: jumpstarter-dev/jumpstarter

Length of output: 198


🏁 Script executed:

# Verify anyio dependency in SNMP driver without full repo clone
find . -name "pyproject.toml" -path "*/jumpstarter-driver-snmp/*" 2>/dev/null | head -5

Repository: jumpstarter-dev/jumpstarter

Length of output: 198


🌐 Web query:

jumpstarter SNMP driver anyio dependency pyproject.toml

💡 Result:

Short answer: jumpstarter-driver-snmp does not list anyio as a dependency — its published package depends on click, jumpstarter-driver-power, pysnmp and jumpstarter. If you need anyio for your project, add it to your pyproject.toml dependencies (example below).

Sources: PyPI jumpstarter-driver-snmp (dependencies list). [1] AnyIO project page for package name. [2]

Example pyproject.toml snippet to add anyio (adjust version constraint as you need):

[project]
dependencies = [
"jumpstarter-driver-snmp",
"anyio>=3.0", # or anyio>=4.0 / >=4.11 depending on your target
]

References:

  1. jumpstarter-driver-snmp — PyPI / package details. [1]
  2. anyio — PyPI / project page. [2]

Add anyio as a runtime dependency in packages/jumpstarter-driver-snmp/pyproject.toml.

Lines 7–8 import anyio (Event, fail_after), but the published SNMP driver package does not declare anyio in its dependencies. This will cause an ImportError at runtime. Add anyio to the dependencies section of the package manifest.

🤖 Prompt for AI Agents
In `@packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py` around
lines 2 - 8, The SNMP driver imports anyio (Event, fail_after) but the package
manifest doesn't declare it; add anyio to the package's dependencies in the
pyproject.toml for the jumpstarter-driver-snmp package (e.g., under [project] or
tool.poetry.dependencies add "anyio" with an appropriate version constraint),
then update lock/install so runtime imports of Event and fail_after from anyio
succeed.

Comment on lines 40 to 42
@dataclass(kw_only=True)
class SNMPServer(Driver):
class SNMPServer(PowerInterface, Driver):
"""SNMP Power Control Driver"""
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 16, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Rename SNMPServer to end with Power now that it implements PowerInterface.

Line 41 makes this a power driver; the naming rule requires a *Power suffix. Please rename and update references.

♻️ Suggested rename (update references accordingly)
-class SNMPServer(PowerInterface, Driver):
+class SNMPPower(PowerInterface, Driver):

As per coding guidelines, power driver class names should end with *Power.

📝 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
@dataclass(kw_only=True)
class SNMPServer(Driver):
class SNMPServer(PowerInterface, Driver):
"""SNMP Power Control Driver"""
`@dataclass`(kw_only=True)
class SNMPPower(PowerInterface, Driver):
"""SNMP Power Control Driver"""
🤖 Prompt for AI Agents
In `@packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py` around
lines 40 - 42, The class currently declared as SNMPServer (which implements
PowerInterface and Driver) should be renamed to end with "Power" (e.g.,
SNMPPower or SNMPServerPower) and all references updated; change the class name
declaration from SNMPServer to the chosen new name and update any imports, type
annotations, factory registrations, tests, and usages that reference SNMPServer
(look for occurrences in jumpstarter_driver_snmp.driver, any places constructing
the driver, isinstance/type checks, and documentation strings) so the symbol
implementing PowerInterface now follows the "*Power" naming convention.

Copy link
Member

Choose a reason for hiding this comment

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

That would make it backwards incompatible and break users

Copy link
Contributor

Choose a reason for hiding this comment

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

@mangelajo, that's a fair point about backwards compatibility. Maintaining existing APIs for users takes priority over naming conventions. The current name SNMPServer can stay as-is. 👍


🧠 Learnings used
Learnt from: CR
Repo: jumpstarter-dev/jumpstarter PR: 0
File: .cursor/rules/creating-new-drivers.mdc:0-0
Timestamp: 2025-11-27T09:58:41.875Z
Learning: Applies to packages/jumpstarter-driver-*/jumpstarter_driver_*/driver.py : Driver class names should be in CamelCase and be descriptive with appropriate suffixes based on functionality: Power drivers should end with `*Power`, Network drivers with `*Network`, Flasher drivers with `*Flasher`, Console drivers with `*Console`, Server drivers with `*Server`

license = "Apache-2.0"
requires-python = ">=3.11"
dependencies = ["jumpstarter", "pillow>=10.4.0"]
dependencies = ["jumpstarter", "pillow>=12.1.0"]
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat packages/jumpstarter-driver-ustreamer/pyproject.toml

Repository: jumpstarter-dev/jumpstarter

Length of output: 958


🌐 Web query:

pillow 12.1.0 python version requirements pypi

💡 Result:

Pillow 12.1.0 requires Python >= 3.10 and is marked as supporting Python 3.10–3.14. [1][2]

Sources:

  • PyPI project page for Pillow (Requires: Python >=3.10; classifiers). [1]
  • Pillow platform support / docs (tested Python versions list). [2]

🏁 Script executed:

# Check if other jumpstarter-driver packages have entry points
fd -t f "pyproject.toml" packages/jumpstarter-driver-* | head -3 | xargs -I {} sh -c 'echo "=== {} ===" && grep -A 5 "entry-points\|jumpstarter.drivers" {}'

Repository: jumpstarter-dev/jumpstarter

Length of output: 718


🏁 Script executed:

# Check full content of ustreamer pyproject.toml for entry-points
grep -n "entry-points" packages/jumpstarter-driver-ustreamer/pyproject.toml || echo "No entry-points found"

Repository: jumpstarter-dev/jumpstarter

Length of output: 92


Missing required jumpstarter.drivers entry point registration.

Driver packages must register via the [project.entry-points."jumpstarter.drivers"] section in pyproject.toml per coding guidelines. This section is absent from the package. Reference other driver packages (e.g., jumpstarter-driver-can, jumpstarter-driver-composite) for the required pattern.

The package otherwise complies with driver naming conventions and includes the required jumpstarter dependency.

🤖 Prompt for AI Agents
In `@packages/jumpstarter-driver-ustreamer/pyproject.toml` at line 13,
pyproject.toml is missing the required entry-point registration for the driver;
add a [project.entry-points."jumpstarter.drivers"] section and register this
package under that group using the module:class target for the driver (follow
the pattern used by jumpstarter-driver-can and jumpstarter-driver-composite),
e.g., add an entry like my_driver_name =
"jumpstarter_driver_ustreamer:UstreamerDriver" replacing
my_driver_name/module/class with the actual package module and driver class name
so jumpstarter can auto-discover the driver.

Copy link
Member

@mangelajo mangelajo left a comment

Choose a reason for hiding this comment

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

@NickCao please test it with the PDUs in the lab to make sure it's stable, other than that it looks good :)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py`:
- Around line 188-190: The read method is annotated to return an
AsyncGenerator[PowerReading, None] but contains no yield so it's a coroutine,
causing TypeError when callers use "async for"; fix by either (A) implementing
it as a true async generator in read (e.g., yield PowerReading items from your
data source or include a no-op "if False: yield" placeholder while implementing)
or (B) change the signature and behavior to a regular async method if power
readings are unsupported (e.g., keep raising NotImplementedError but update the
return annotation to an appropriate coroutine/None type such as "-> None" or "->
Awaitable[None]" and adjust callers accordingly). Ensure you modify the read
function definition and its type annotation (the exported async def read)
consistently.

In `@packages/jumpstarter-driver-uboot/pyproject.toml`:
- Line 22: The package is missing the required entry-point registration; add a
[project.entry-points."jumpstarter.drivers"] section to pyproject.toml in the
jumpstarter-driver-uboot package and register this driver under a stable key
(e.g., "uboot") mapped to the package import path that exposes the driver
implementation (for example the module and object that implements the driver,
such as my_module:MyDriver or package.module:driver_factory). Ensure the
entry-point key and import path match the actual driver implementation symbol in
the package so Jumpstarter can discover it.

In `@packages/jumpstarter/pyproject.toml`:
- Line 18: The pyproject declares "pydantic>=2.12.5" while pydantic-settings in
our deps doesn't support Python 3.14; either upgrade the pydantic-settings
package to a release that adds Python 3.14 support or tighten the project Python
constraint to exclude 3.14. Locate the pydantic entry ("pydantic>=2.12.5") and
the project metadata key requires-python and then (a) bump the pydantic-settings
requirement to a 3.14-compatible version in pyproject.toml or (b) change
requires-python to a range that excludes 3.14 (e.g., "<3.14") so the current
pydantic-settings remains valid.
♻️ Duplicate comments (1)
packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1)

7-8: Ensure anyio is added as a runtime dependency.

This has been flagged in a previous review but remains unresolved. The import of Event and fail_after from anyio will cause ImportError at runtime if the package isn't declared in pyproject.toml.

"anyio>=4.4.0,!=4.6.2",
"aiohttp>=3.10.5",
"pydantic>=2.8.2",
"pydantic>=2.12.5",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -path "*/packages/jumpstarter/pyproject.toml" -type f

Repository: jumpstarter-dev/jumpstarter

Length of output: 108


🏁 Script executed:

cat -n packages/jumpstarter/pyproject.toml | head -40

Repository: jumpstarter-dev/jumpstarter

Length of output: 1330


🌐 Web query:

pydantic 2.12.5 pydantic-settings 2.9.1 compatibility

💡 Result:

Yes — pydantic-settings 2.9.1 is compatible with Pydantic 2.12.5. pydantic-settings 2.9.1 declares a dependency of pydantic >= 2.7.0, so Pydantic 2.12.5 satisfies that requirement. [1][2]

Sources:

  • Fedora package metadata (pydantic-settings 2.9.1 requires python3.13dist(pydantic) >= 2.7). [1]
  • pydantic-settings dependency listing (pydantic >= 2.7.0). [2]

🌐 Web query:

pydantic-settings 2.9.1 python 3.14 support

💡 Result:

Short answer: No — pydantic-settings 2.9.1 (released May 23, 2025) does not include official Python 3.14 support. Upgrade to a pydantic release with 3.14 support (pydantic v2.12+ adds initial Python 3.14 support). [1][2]

Sources:

  • pydantic-settings 2.9.1 release on PyPI (May 23, 2025). [1]
  • Pydantic v2.12 release / changelog — adds initial Python 3.14 support. [2]

🌐 Web query:

pydantic 2.12.5 python 3.14 support

💡 Result:

Yes — the Pydantic 2.12 series adds initial Python 3.14 support, and 2.12.5 is part of that release line. See the v2.12 release notes (Python 3.14 support highlighted) and the PyPI release for 2.12.5. [1][2]

Sources:
[1] Pydantic v2.12 release announcement (notes: "Support for Python 3.14").
[2] pydantic on PyPI — pydantic 2.12.5 release files.


Update pydantic-settings to a version with Python 3.14 support.

Pydantic 2.12.5 is compatible with pydantic-settings 2.9.1 (which requires pydantic ≥2.7.0). However, pydantic-settings 2.9.1 does not support Python 3.14, while pydantic 2.12.5 does. Since the project declares requires-python = ">=3.11" (allowing Python 3.14) and includes a Python 3.14-specific dependency (backports-zstd), you need to either upgrade pydantic-settings to a version with Python 3.14 support or restrict the Python version constraint to exclude 3.14.

🤖 Prompt for AI Agents
In `@packages/jumpstarter/pyproject.toml` at line 18, The pyproject declares
"pydantic>=2.12.5" while pydantic-settings in our deps doesn't support Python
3.14; either upgrade the pydantic-settings package to a release that adds Python
3.14 support or tighten the project Python constraint to exclude 3.14. Locate
the pydantic entry ("pydantic>=2.12.5") and the project metadata key
requires-python and then (a) bump the pydantic-settings requirement to a
3.14-compatible version in pyproject.toml or (b) change requires-python to a
range that excludes 3.14 (e.g., "<3.14") so the current pydantic-settings
remains valid.

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.

2 participants