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

Dedup output mode handling (new design)#463

Merged
NickCao merged 1 commit intomainfrom
output-mode-new
Jun 18, 2025
Merged

Dedup output mode handling (new design)#463
NickCao merged 1 commit intomainfrom
output-mode-new

Conversation

@NickCao
Copy link
Copy Markdown
Collaborator

@NickCao NickCao commented May 8, 2025

Summary by CodeRabbit

  • Refactor
    • Replaced multiple resource-specific print functions with a unified model_print for consistent output handling.
    • Simplified listing functions to delegate all formatting to model_print, removing manual format logic.
    • Updated resource list methods to return richer models supporting rich display features.
    • Removed legacy serialization methods (dump_json, dump_yaml) in favor of model_print.
    • Removed legacy table generation utility and associated tests, consolidating output rendering with rich.
    • Converted asynchronous driver listing function to synchronous, updating table rendering accordingly.
  • New Features
    • Added rich display methods (rich_add_columns, rich_add_rows, rich_add_names) to resource classes for enhanced table visualization.
  • Bug Fixes
    • Corrected configuration list length checks to evaluate the items attribute, ensuring accurate default setting logic.
  • Tests
    • Modified tests to expect successful exit codes (0) when resources are absent, aligning with updated CLI behavior.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 8, 2025

Deploy Preview for jumpstarter-docs ready!

Name Link
🔨 Latest commit 2f9fa2f
🔍 Latest deploy log https://app.netlify.com/projects/jumpstarter-docs/deploys/6852bd2195a09d00083d0fb0
😎 Deploy Preview https://deploy-preview-463--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
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2025

Walkthrough

This update introduces a centralized model_print function for rendering resource models in various formats (JSON, YAML, name, or table). Resource classes gain methods for rich display, and CLI commands are refactored to delegate all output to model_print. Client and exporter config listing methods are adjusted to return rich display-enabled list objects, with legacy print functions removed.

Changes

Files / Groups Change Summary
packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py,
get.py,
import_res.py
Removed local print functions and output mode checks; now delegate output to model_print. Fixed client config list access to use .items.
packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py Updated tests to expect exit code 0 (success) when no resources found, instead of exit code 1.
packages/jumpstarter-cli-admin/jumpstarter_cli_admin/print.py Deleted file containing all resource-specific print and table formatting functions/constants.
packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py Added model_print function to handle model output in JSON, YAML, name, or table format using rich.
packages/jumpstarter-cli/jumpstarter_cli/config_client.py,
config_exporter.py,
create.py,
get.py,
update.py
Replaced manual output formatting and table construction with calls to model_print. Adjusted client and exporter config listing to use new list object with .items.
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py,
exporters.py,
leases.py
Added rich_add_columns, rich_add_rows, and rich_add_names methods to resource and list classes for rich table display.
packages/jumpstarter/jumpstarter/client/grpc.py Removed dump_json/dump_yaml methods; added rich_add_columns, rich_add_rows, and rich_add_names for rich table support.
packages/jumpstarter/jumpstarter/config/client.py Changed ClientConfigV1Alpha1.list to return ClientConfigListV1Alpha1 object; added rich display methods to the list class; removed legacy serialization methods.
packages/jumpstarter/jumpstarter/config/client_config_test.py Updated tests to use .items from ClientConfigV1Alpha1.list() result.
packages/jumpstarter/jumpstarter/config/exporter.py Changed ExporterConfigV1Alpha1.list to return ExporterConfigListV1Alpha1; added rich display methods; removed legacy serialization methods.
packages/jumpstarter-cli-common/jumpstarter_cli_common/table.py Deleted legacy make_table function replaced by model_print.
packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py Deleted legacy test for make_table.
packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py Changed list_drivers from async to sync; replaced make_table with rich.Table and Console.print.

Sequence Diagram(s)

sequenceDiagram
    participant CLI_Command
    participant Model
    participant model_print
    participant RichConsole

    CLI_Command->>Model: Retrieve resource(s)
    CLI_Command->>model_print: Call with (model, output_mode, kwargs)
    alt output_mode is JSON
        model_print->>Model: model_dump_json()
        model_print->>RichConsole: Print JSON
    else output_mode is YAML
        model_print->>Model: model_dump()
        model_print->>RichConsole: Print YAML
    else output_mode is NAME or PATH
        model_print->>Model: rich_add_names/paths()
        model_print->>RichConsole: Print names/paths
    else
        model_print->>Model: rich_add_columns(table)
        model_print->>Model: rich_add_rows(table)
        model_print->>RichConsole: Print table or "No resources found"
    end
Loading

Possibly related PRs

Suggested reviewers

  • mangelajo
  • kirkbrauer

Poem

🐇
A single print for every case,
No more branching, what a pace!
Tables, names, or YAML streams,
Unified output—rabbit dreams.
Models now can strut and show,
In JSON, rich, or CLI flow!
Hooray for code that’s neat and bright—
Output handled just right!

✨ 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
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (8)
packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (1)

9-70: Excellent unified printing implementation that eliminates duplication across the codebase.

This model_print function elegantly centralizes output formatting by leveraging rich display methods defined on model classes. It handles all output formats (JSON, YAML, name, path, and table) in a consistent way while delegating the specifics of what to display to the models themselves.

A few observations:

  • The match statement is used correctly to handle different output modes
  • Error handling is appropriate, raising NotImplementedError with the original AttributeError as context
  • Table formatting is clean with sensible defaults

Consider addressing the TODO comment on line 68 to also print the namespace when no resources are found, which would provide more context to users.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (1)

56-70: Good implementation of rich display methods for individual client objects.

These methods properly implement the interface expected by model_print for formatting client details into a table or list of names.

Consider implementing the commented "AGE" column at line 60 to show resource age, which would be useful for users tracking when clients were created.

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

257-284: Well-structured refactor to return a ClientConfigListV1Alpha1 object

The list method has been updated to return a ClientConfigListV1Alpha1 instance instead of a plain list, which aligns with the unified output format approach. Good addition of the current_config field to track the currently active client.

Consider adding error handling for the case where UserConfigV1Alpha1.load() might fail due to malformed but existing files.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (1)

74-96: Comprehensive row formatting implementation

The implementation correctly handles both device-level details and summary views. Good handling of optional fields and label formatting.

One suggestion for consistency: in line 94, you check both self.status and self.status.devices, but in line 76 you only check self.status. Consider using consistent null-checking patterns throughout the method.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (2)

92-108: Well-structured reason mapping

The get_reason method intelligently maps condition reasons and statuses to user-friendly strings, improving readability in the CLI output.

For robustness, consider adding a null check for self.status.conditions before accessing it, in case it's None.


109-124: Thorough row formatting with selector handling

Good implementation for formatting lease data into table rows, including nice handling of selector labels.

Consider adding a null check for self.spec.selector.match_labels before iterating over it, to prevent potential errors if it's None.

        selectors = []
-       for label in self.spec.selector.match_labels:
+       if self.spec.selector and self.spec.selector.match_labels:
+           for label in self.spec.selector.match_labels:
+               selectors.append(f"{label}:{str(self.spec.selector.match_labels[label])}")
-           selectors.append(f"{label}:{str(self.spec.selector.match_labels[label])}")
packages/jumpstarter/jumpstarter/client/grpc.py (2)

52-57: Consider more readable label formatting

The current approach to formatting labels joins them with commas, which works but could become difficult to read with many labels.

- ",".join(("{}={}".format(i[0], i[1]) for i in self.labels.items())),
+ ", ".join("{}={}".format(k, v) for k, v in self.labels.items()),

This small change adds spaces after commas and uses more descriptive variable names for better readability.


116-124: Consider adding condition status information

The rich_add_rows implementation displays the core lease properties but doesn't show any condition status information, which might be important for understanding lease state. Consider adding a column for lease status based on conditions.

 @classmethod
 def rich_add_columns(cls, table):
     table.add_column("NAME")
     table.add_column("SELECTOR")
     table.add_column("DURATION")
     table.add_column("CLIENT")
     table.add_column("EXPORTER")
+    table.add_column("STATUS")

 def rich_add_rows(self, table):
+    status = "Unknown"
+    for condition in self.conditions:
+        if condition.type == "Ready" and condition.status:
+            status = condition.status
+            break
     table.add_row(
         self.name,
         self.selector,
         str(self.duration),
         self.client,
         self.exporter,
+        status,
     )
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d346847 and 68f0966.

📒 Files selected for processing (18)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py (3 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py (4 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py (4 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/print.py (0 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (1 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/config_client.py (4 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/config_exporter.py (2 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/create.py (2 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/get.py (3 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/update.py (2 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (2 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (2 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (2 hunks)
  • packages/jumpstarter/jumpstarter/client/grpc.py (4 hunks)
  • packages/jumpstarter/jumpstarter/config/client.py (4 hunks)
  • packages/jumpstarter/jumpstarter/config/client_config_test.py (1 hunks)
  • packages/jumpstarter/jumpstarter/config/exporter.py (2 hunks)
💤 Files with no reviewable changes (1)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/print.py
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py (1)
packages/jumpstarter/jumpstarter/config/client.py (1)
  • ClientConfigV1Alpha1 (54-293)
packages/jumpstarter-cli/jumpstarter_cli/config_exporter.py (2)
packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (1)
  • model_print (9-70)
packages/jumpstarter/jumpstarter/config/exporter.py (1)
  • ExporterConfigV1Alpha1 (72-175)
packages/jumpstarter-cli/jumpstarter_cli/config_client.py (2)
packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (1)
  • model_print (9-70)
packages/jumpstarter/jumpstarter/config/client.py (2)
  • ClientConfigV1Alpha1 (54-293)
  • ClientConfigV1Alpha1Drivers (49-51)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (4)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (6)
  • rich_add_columns (57-60)
  • rich_add_columns (80-81)
  • rich_add_rows (62-66)
  • rich_add_rows (83-85)
  • rich_add_names (68-69)
  • rich_add_names (87-89)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (6)
  • rich_add_columns (80-90)
  • rich_add_columns (138-139)
  • rich_add_rows (109-124)
  • rich_add_rows (141-143)
  • rich_add_names (126-127)
  • rich_add_names (145-147)
packages/jumpstarter/jumpstarter/config/exporter.py (3)
  • rich_add_columns (186-188)
  • rich_add_rows (190-195)
  • rich_add_names (197-199)
packages/jumpstarter/jumpstarter/config/client.py (3)
  • rich_add_columns (305-309)
  • rich_add_rows (311-318)
  • rich_add_names (320-322)
packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (4)
packages/jumpstarter-cli-common/jumpstarter_cli_common/opt.py (1)
  • OutputMode (41-45)
packages/jumpstarter/jumpstarter/config/exporter.py (3)
  • rich_add_names (197-199)
  • rich_add_columns (186-188)
  • rich_add_rows (190-195)
packages/jumpstarter/jumpstarter/config/client.py (3)
  • rich_add_names (320-322)
  • rich_add_columns (305-309)
  • rich_add_rows (311-318)
packages/jumpstarter/jumpstarter/client/grpc.py (12)
  • rich_add_names (58-59)
  • rich_add_names (125-126)
  • rich_add_names (148-150)
  • rich_add_names (172-174)
  • rich_add_columns (48-50)
  • rich_add_columns (109-114)
  • rich_add_columns (141-142)
  • rich_add_columns (165-166)
  • rich_add_rows (52-56)
  • rich_add_rows (116-123)
  • rich_add_rows (144-146)
  • rich_add_rows (168-170)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (2)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (6)
  • rich_add_columns (61-72)
  • rich_add_columns (110-111)
  • rich_add_rows (74-96)
  • rich_add_rows (113-115)
  • rich_add_names (98-99)
  • rich_add_names (117-119)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (6)
  • rich_add_columns (57-60)
  • rich_add_columns (80-81)
  • rich_add_rows (62-66)
  • rich_add_rows (83-85)
  • rich_add_names (68-69)
  • rich_add_names (87-89)
packages/jumpstarter/jumpstarter/client/grpc.py (3)
packages/jumpstarter/jumpstarter/config/client.py (4)
  • rich_add_columns (305-309)
  • rich_add_rows (311-318)
  • rich_add_names (320-322)
  • lease (81-89)
packages/jumpstarter/jumpstarter/common/metadata.py (1)
  • name (13-14)
packages/jumpstarter/jumpstarter/client/lease.py (1)
  • Lease (31-211)
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: pytest-matrix (3.13)
  • GitHub Check: pytest-matrix (3.12)
  • GitHub Check: pytest-matrix (3.11)
  • GitHub Check: e2e
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter-devspace .devfile/Containerfile.client)
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter Dockerfile)
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter-utils Dockerfile.utils)
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter-dev .devfile/Containerfile)
🔇 Additional comments (55)
packages/jumpstarter/jumpstarter/config/client_config_test.py (3)

328-328: Update to access .items correctly.

This change reflects the new structure where ClientConfigV1Alpha1.list() now returns a structured object with an items attribute containing the list of configurations, rather than returning a plain list directly.


336-336: Consistent use of .items for accessing client configs.

Properly updated to access the list items through the .items attribute, maintaining test compatibility with the new return type.


342-342: Updated empty list check for new return type.

The test now correctly verifies an empty list using the .items attribute on the returned object, aligned with the new function return structure.

packages/jumpstarter-cli/jumpstarter_cli/create.py (2)

6-7: Updated imports to support the new output handling approach.

Correctly importing the OutputType from the common package and the new model_print function that centralizes output formatting.


53-53: Simplified output handling using central model_print function.

This change elegantly replaces the previous custom output formatting code with a call to the centralized model_print function, improving code maintainability and ensuring consistent output handling across the CLI.

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

81-81: Updated to access client configs through .items attribute.

This correctly adapts the condition to the new ClientConfigV1Alpha1.list() return type, which now returns an object with an items attribute instead of a direct list.

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py (4)

270-271: Updated test expectation for "no resources found" case.

Changed the expected exit code from 1 to 0, reflecting the new standardized behavior where "no resources found" is treated as a successful execution with a specific message rather than an error condition.


639-640: Consistent exit code for "no exporters found" case.

Test now expects exit code 0 for the "no resources found" case, maintaining consistency with the updated output handling approach across the CLI.


803-804: Aligned exit code expectations for empty exporter devices list.

Updated to expect exit code 0 when no exporter devices are found, consistent with the new standardized behavior.


1196-1197: Standardized exit code for empty lease listing.

Test now consistently expects exit code 0 for "no leases found", completing the standardization of "no resources found" handling across all resource types.

packages/jumpstarter-cli/jumpstarter_cli/update.py (2)

6-7: Imports updated to use new output formatting utility.

The imports have been updated to use the new model_print function from jumpstarter_cli_common.print instead of the previous output formatting utilities.


32-32: Output formatting delegated to unified model_print function.

The code now uses the unified model_print function instead of explicit conditional logic for different output modes. This simplifies the code and ensures consistent output formatting across the CLI.

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

13-13: Import added for unified model_print function.

The import of model_print from jumpstarter_cli_common.print supports the new unified output formatting approach.


48-48: Replaced client-specific printing with model_print.

The code now delegates client output formatting to the unified model_print function, improving consistency and reducing duplication across commands.


51-51: Replaced clients list printing with model_print.

Multiple clients output formatting is now handled by the unified model_print function.


79-79: Replaced exporter-specific printing with model_print.

The code now passes both the exporter and the devices flag to model_print, preserving the behavior of showing device information when requested.


82-82: Replaced exporters list printing with model_print.

Multiple exporters output formatting is now handled by the unified model_print function, with preserved devices display functionality.


104-104: Replaced lease-specific printing with model_print.

The code now delegates lease output formatting to the unified model_print function.


107-107: Replaced leases list printing with model_print.

Multiple leases output formatting is now handled by the unified model_print function.

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

9-9: Import added for unified model_print function.

The import of model_print from jumpstarter_cli_common.print supports the new unified output formatting approach.


11-11: Simplified imports by removing ExporterConfigListV1Alpha1.

The ExporterConfigListV1Alpha1 import has been removed since it's not directly referenced in this file. According to the provided context, ExporterConfigV1Alpha1.list() already returns an instance of ExporterConfigListV1Alpha1.


82-82: Replaced exporter config list printing with model_print.

The code now delegates output formatting to the unified model_print function, removing the need for conditional logic based on output mode. This simplifies the code and ensures consistent output formatting.

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

4-5: Imports updated to use new output formatting utility.

The imports have been updated to use the new model_print function from jumpstarter_cli_common.print instead of the previous output formatting utilities.


29-29: Replaced exporters list printing with model_print.

Output formatting for the list of exporters is now delegated to the unified model_print function, simplifying the code and ensuring consistent output.


44-44: Replaced leases list printing with model_print.

Output formatting for the list of leases is now delegated to the unified model_print function, simplifying the code and ensuring consistent output.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (1)

79-90: Clean implementation of list display methods delegating to individual items.

The list implementation correctly delegates to the individual client methods, maintaining the separation of concerns and avoiding code duplication.

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

12-12: Good replacement of table-specific import with generic model_print.


96-96: Updated list access pattern to match new structure.

Correctly updated to access the items attribute on the list result, which aligns with the changes in list return types.


112-112: Consistent use of items attribute access.


139-139: Simplified output with unified model_print function.

Eliminated manual output formatting logic, making the code cleaner and easier to maintain.

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

15-15: Good import of the unified model_print function.


104-104: Consistent update to access items attribute.

Correctly updated to access the items attribute on the list result, matching the pattern in config_client.py.


110-110: Replaced custom print function with model_print.

Simplified output formatting by using the unified model_print function, improving consistency across commands.


166-166: Consistent use of model_print for exporter output.

Applied the same pattern for exporter output, ensuring consistency across different resource types.

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

304-319: Well-implemented rich display support

The rich_add_columns and rich_add_rows methods provide a clean implementation for table-based display. The approach of marking the current config with "*" is intuitive for CLI users.


320-322: Good name collection implementation

The rich_add_names method correctly appends all client aliases to the provided list, supporting the name-only output mode.

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

112-117: Appropriate refactor of the list method

This update to return a list model rather than a raw list aligns with the new output formatting approach and follows the same pattern implemented across other resources.


183-183: Useful model_config addition

The model_config addition enables proper handling of aliases and arbitrary types, which supports the serialization requirements for rich output formatting.


186-195: Well-structured rich table columns and rows

These methods appropriately define and populate the table columns and rows for exporter configurations, providing a consistent display mechanism.


197-199: Proper name collection implementation

The rich_add_names method correctly implements the name-only output mode pattern used by the centralized printing utility.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (2)

61-72: Flexible column definition with device mode support

The conditional column setup based on the devices flag provides a nice flexible output format. This allows both summary views and detailed device views using the same underlying code.


98-99: Clear resource naming format

The rich_add_names method correctly formats exporter names with their resource type prefix, which is helpful for CLI users.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (3)

80-90: Comprehensive lease table columns

The column definitions cover all important lease attributes, providing a complete view of lease information in table output mode.


126-127: Consistent resource naming pattern

The format matches the pattern used in other resource types, providing a consistent experience across different resource kinds.


138-147: Well-implemented list class methods

These methods correctly delegate to the instance methods of each contained lease, following the pattern used across other resource list types.

packages/jumpstarter/jumpstarter/client/grpc.py (10)

47-51: Appropriate column definition for exporters

The implementation of rich_add_columns provides a clean structure for displaying exporter information. The column headers are concise and descriptive.


58-60: Simple and effective name collection method

The rich_add_names implementation is clean and efficient for collecting exporter names.


108-115: Complete column structure for lease display

The column headers cover all important lease attributes, facilitating effective data presentation.


125-127: Consistent name collection for leases

The implementation follows the same pattern as other entities, maintaining consistency across the codebase.


140-143: Efficient reuse of Exporter column definition

Good delegation to the Exporter class for column definitions, promoting code reuse and ensuring consistency.


144-147: Clean implementation for handling multiple exporters

The method efficiently iterates through exporters and delegates row addition to each instance.


148-151: Consistent name collection for exporter lists

Follows the established pattern for name collection, maintaining consistency across the codebase.


164-167: Efficient reuse of Lease column definition

Good delegation to the Lease class for column definitions, promoting code reuse and ensuring consistency.


168-171: Clean implementation for handling multiple leases

The method efficiently iterates through leases and delegates row addition to each instance.


172-175: Consistent name collection for lease lists

Follows the established pattern for name collection, maintaining consistency across the codebase.

Comment thread packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py Outdated
@NickCao NickCao force-pushed the output-mode-new branch 4 times, most recently from 25560aa to de586fb Compare May 9, 2025 15:35
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (1)

9-75: 🛠️ Refactor suggestion

Consider refactoring to reduce complexity and improve error handling.

The function works well but has some areas for improvement:

  1. The # noqa: C901 comment indicates high cyclomatic complexity. Consider extracting each output mode handler into separate methods.
  2. Using AttributeError to detect missing methods is fragile. Consider using hasattr() checks instead.
  3. The error messages could be more helpful by specifying which methods are required for each output mode.

Apply this refactor to improve error handling and clarity:

-            try:
-                model.rich_add_names(names)
-            except AttributeError as err:
-                raise NotImplementedError from err
+            if not hasattr(model, 'rich_add_names'):
+                raise NotImplementedError(
+                    f"Model {model.__class__.__name__} must implement rich_add_names() for NAME output mode"
+                )
+            model.rich_add_names(names)

Similar changes should be applied to the PATH and table output modes.

🧹 Nitpick comments (3)
packages/jumpstarter/jumpstarter/config/exporter.py (1)

190-195: Handle potential None value for exporter path.

The str(exporter.path) on line 194 will display "None" if an exporter doesn't have a path set. Consider displaying an empty string or a placeholder instead.

Apply this improvement:

     def rich_add_rows(self, table):
         for exporter in self.items:
             table.add_row(
                 exporter.alias,
-                str(exporter.path),
+                str(exporter.path) if exporter.path else "",
             )
packages/jumpstarter/jumpstarter/config/client.py (1)

311-318: Handle potential None value for client path.

Similar to the exporter config, str(client.path) will display "None" if a client doesn't have a path set.

Apply this improvement:

     def rich_add_rows(self, table):
         for client in self.items:
             table.add_row(
                 "*" if self.current_config == client.alias else "",
                 client.alias,
                 client.endpoint,
-                str(client.path),
+                str(client.path) if client.path else "",
             )
packages/jumpstarter/jumpstarter/client/grpc.py (1)

108-115: Consider column consistency with Kubernetes lease implementation.

The column order and selection differs from the Kubernetes lease implementation in the other file. While this may be intentional due to different data availability, consider if consistency would improve user experience.

The Kubernetes lease has columns: NAME, CLIENT, SELECTOR, EXPORTER, DURATION, STATUS, REASON, BEGIN, END, AGE
This gRPC lease has: NAME, SELECTOR, DURATION, CLIENT, EXPORTER

Consider if STATUS, REASON, and AGE columns would be valuable here as well.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 25560aa and 9265a67.

📒 Files selected for processing (21)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py (3 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py (4 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py (4 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/print.py (0 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (1 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table.py (0 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py (0 hunks)
  • packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py (1 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/config_client.py (4 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/config_exporter.py (2 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/create.py (2 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/get.py (3 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/update.py (2 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (2 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (3 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (3 hunks)
  • packages/jumpstarter/jumpstarter/client/grpc.py (4 hunks)
  • packages/jumpstarter/jumpstarter/config/client.py (4 hunks)
  • packages/jumpstarter/jumpstarter/config/client_config_test.py (1 hunks)
  • packages/jumpstarter/jumpstarter/config/exporter.py (2 hunks)
💤 Files with no reviewable changes (3)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table.py
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/print.py
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: Header rules - jumpstarter-docs
  • GitHub Check: Pages changed - jumpstarter-docs
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: pytest-matrix (macos-15, 3.11)
  • GitHub Check: pytest-matrix (macos-15, 3.13)
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter-utils Dockerfile.utils)
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter-dev .devfile/Containerfile)
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter Dockerfile)
  • GitHub Check: build-and-push-image (jumpstarter-dev/jumpstarter-devspace .devfile/Containerfile.client)
🔇 Additional comments (37)
packages/jumpstarter/jumpstarter/config/client_config_test.py (1)

328-328: LGTM!

The test updates correctly adapt to the new API where ClientConfigV1Alpha1.list() returns an object with an items attribute rather than returning the list directly. These changes maintain the test logic while aligning with the refactored list method implementation.

Also applies to: 336-336, 342-342

packages/jumpstarter-cli/jumpstarter_cli/create.py (1)

6-7: Clean refactoring to centralize output handling!

The replacement of the explicit output mode handling with model_print(lease, output) aligns perfectly with the PR objective. This change eliminates code duplication and centralizes all output formatting logic, making the codebase more maintainable.

Also applies to: 53-53

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

87-87: LGTM!

The update correctly adapts to the new API where ClientConfigV1Alpha1.list() returns an object with an items attribute. The logic for setting the first imported client as default remains intact.

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

13-13: Good refactoring to centralized output handling.

The import of model_print aligns with the PR's objective to deduplicate output mode handling.


48-51: Consistent implementation of centralized output handling.

All calls to model_print correctly:

  • Pass the model object as the first argument
  • Pass the output format as the second argument
  • Include namespace=namespace as a keyword argument
  • For exporters, include the devices flag when needed

The refactoring successfully removes duplicate output logic and centralizes it in the model_print function.

Also applies to: 79-82, 104-107

packages/jumpstarter-cli/jumpstarter_cli/get.py (2)

4-5: Clean import refactoring.

The removal of OutputMode and make_table imports, replaced by model_print, demonstrates the successful consolidation of output handling logic.


29-29: Excellent simplification of output handling.

The replacement of complex match statements with simple model_print calls significantly improves code maintainability and readability. The centralized output handling ensures consistency across all commands.

Also applies to: 44-44

packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py (1)

9-9: Why was the function changed from async to sync?

The change from async def to def is not explained in the PR description. Was this necessary for the new output handling design?

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

17-17: Good refactoring to centralize output handling!

The migration to use the centralized model_print function improves modularity and follows the DRY principle. The change to access .items is consistent with the updated return type of ClientConfigV1Alpha1.list().

Also applies to: 110-110, 116-116, 176-176

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

259-259: Address circular import pattern.

Importing UserConfigV1Alpha1 inside the method suggests a circular dependency issue. While this works, it indicates a potential architectural problem that should be addressed.

Consider refactoring the module structure to avoid circular imports, or document why this pattern is necessary here.

packages/jumpstarter-cli/jumpstarter_cli/update.py (1)

6-7: Clean refactoring to centralize output handling!

The replacement of the match statement with model_print simplifies the code and aligns with the PR's objective of deduplicating output mode handling.

Also applies to: 32-32

packages/jumpstarter-cli/jumpstarter_cli/config_exporter.py (1)

9-9:

Details

✅ Verification successful

Verify that the list() method returns a model with rich display methods

The refactoring looks good. The removal of ExporterConfigListV1Alpha1 import suggests that ExporterConfigV1Alpha1.list() now returns a model with built-in rich display capabilities.

Also applies to: 11-11, 82-82


🏁 Script executed:

#!/bin/bash
# Description: Verify that ExporterConfigV1Alpha1.list() returns a model with the required rich display methods

# Check the return type and implementation of list() method
ast-grep --pattern 'class ExporterConfigV1Alpha1 {
  $$$
  list($$$) {
    $$$
  }
  $$$
}'

# Also search for the list method implementation
rg -A 10 "def list.*ExporterConfig" --type py

Length of output: 1162


🏁 Script executed:

#!/bin/bash
# Locate and inspect the class definition for ExporterConfigListV1Alpha1
rg -n "class ExporterConfigListV1Alpha1" packages/jumpstarter/jumpstarter/config/exporter.py
rg -A 20 "class ExporterConfigListV1Alpha1" packages/jumpstarter/jumpstarter/config/exporter.py

Length of output: 984


ExporterConfigV1Alpha1.list() return type validated

The list() method still returns an ExporterConfigListV1Alpha1, which defines rich_add_columns, rich_add_rows, and rich_add_names for rich display. No further changes are needed here.

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

12-14: Import changes look good!

The migration from make_table to model_print and the removal of unused import align well with the centralized output handling approach.


96-96: Consistent with the new list API design.

The change correctly accesses the .items property of the list object returned by the refactored list() method.


112-112: Iteration correctly updated for the new API.

The loop properly iterates over the .items property of the list object.


137-139: Excellent simplification of output handling!

The centralized model_print function elegantly handles all output formats, removing the need for conditional logic and improving maintainability.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (3)

56-61: Well-implemented rich display column definition.

The class method correctly defines the table columns for client display.


62-70: Rich display methods properly implemented.

Both rich_add_rows and rich_add_names are well-implemented with appropriate null safety for the status field.


79-90: List class methods correctly delegate to item methods.

The implementation properly iterates over items and delegates to the corresponding methods.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (4)

8-8: Required import for time display.

The time_since import is properly added to support the AGE column in the rich display.


61-74: Flexible column definition with device mode support.

The method correctly handles two display modes with appropriate columns for each view.


75-98: Comprehensive row generation with proper null safety.

The method correctly handles both display modes with appropriate null checks and label formatting.


118-121: Methods correctly implemented with past issue resolved.

The rich_add_names parameter naming issue from the previous review has been fixed - the parameter is now correctly named names instead of table.

packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (5)

80-92: LGTM! Well-structured table column definitions.

The column headers are comprehensive and appropriate for lease resource display.


93-109: LGTM! Safe condition handling with clear status mapping.

The method properly checks for empty conditions before accessing the last element and provides clear status interpretation logic.


110-125: LGTM! Good null safety and data formatting.

The method handles potential None values appropriately and formats complex data (selectors) clearly for display.


127-129: LGTM! Simple and correct name formatting.

The method properly formats the lease name with its resource type prefix.


138-149: LGTM! Proper delegation pattern for list operations.

The list class methods correctly delegate to individual item methods, following good OOP patterns.

packages/jumpstarter/jumpstarter/client/grpc.py (9)

47-51: LGTM! Clear column definitions for exporter display.

The columns are appropriate for displaying exporter information.


52-57: LGTM! Proper label formatting.

The method correctly formats labels as key=value pairs and handles empty labels gracefully.


58-60: LGTM! Simple name appending.

The method correctly appends the exporter name.


116-124: LGTM! Clean data formatting for table display.

The method properly converts duration to string and handles the data appropriately.


125-127: LGTM! Simple name appending.

The method correctly appends the lease name.


140-147: LGTM! Proper delegation pattern for list operations.

The list class methods correctly delegate to individual item methods.


148-151: LGTM! Consistent delegation pattern.

The method follows the same delegation pattern as other list methods.


164-171: LGTM! Proper delegation pattern for list operations.

The list class methods correctly delegate to individual item methods.


172-175: LGTM! Consistent delegation pattern.

The method follows the same delegation pattern as other list methods.

Comment thread packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py
Comment thread packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py
Comment thread packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py
Comment thread packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py
@NickCao NickCao force-pushed the output-mode-new branch 3 times, most recently from d507ba0 to e76e7f7 Compare May 28, 2025 15:37
Copy link
Copy Markdown
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.

This is good, sorry for taking so long, now there is at least a conflict :-/

@NickCao NickCao enabled auto-merge June 18, 2025 13:22
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (1)

6-6: time_since robustness already flagged earlier
Previous review noted that time_since must accept both datetime objects and ISO-8601 strings (with/without fractional seconds). Make sure the updated implementation landed before relying on it here.

🧹 Nitpick comments (3)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (3)

80-92: Column metadata looks good – consider widths/no-wrap
The column set matches the row data. If very long selector strings are expected, consider setting no_wrap=True or a max_width on the “SELECTOR” column to keep tables readable, but that’s optional.


93-109: Remove redundant else blocks & simplify logic
Two return statements make the trailing else unnecessary and slightly deepen the nesting. A small refactor improves readability:

 def get_reason(self):
     condition = self.status.conditions[-1] if self.status.conditions 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
+    reason = condition.reason if condition else "Unknown"
+    status = condition.status if condition else "False"
+
+    if reason == "Ready":
+        return "Ready" if status == "True" else "Waiting"
+    if reason == "Expired":
+        return "Expired" if status == "True" else "Complete"
+    return reason

112-114: Use dictionary iteration for clarity
Minor readability nit – iterate directly over dict.items() instead of indexing by key.

-        selectors = []
-        for label in self.spec.selector.match_labels:
-            selectors.append(f"{label}:{str(self.spec.selector.match_labels[label])}")
+        selectors = [
+            f"{key}:{value}"
+            for key, value in self.spec.selector.match_labels.items()
+        ]
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e76e7f7 and 2f9fa2f.

📒 Files selected for processing (21)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py (3 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py (4 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py (4 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py (1 hunks)
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/print.py (0 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py (1 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table.py (0 hunks)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py (0 hunks)
  • packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py (1 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/config_client.py (4 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/config_exporter.py (2 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/create.py (2 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/get.py (3 hunks)
  • packages/jumpstarter-cli/jumpstarter_cli/update.py (2 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py (2 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py (3 hunks)
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py (3 hunks)
  • packages/jumpstarter/jumpstarter/client/grpc.py (4 hunks)
  • packages/jumpstarter/jumpstarter/config/client.py (5 hunks)
  • packages/jumpstarter/jumpstarter/config/client_config_test.py (1 hunks)
  • packages/jumpstarter/jumpstarter/config/exporter.py (2 hunks)
💤 Files with no reviewable changes (3)
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/table.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/print.py
🚧 Files skipped from review as they are similar to previous changes (17)
  • packages/jumpstarter-cli/jumpstarter_cli/get.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py
  • packages/jumpstarter/jumpstarter/config/client_config_test.py
  • packages/jumpstarter-cli/jumpstarter_cli/update.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py
  • packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py
  • packages/jumpstarter-cli/jumpstarter_cli/create.py
  • packages/jumpstarter-cli/jumpstarter_cli/config_exporter.py
  • packages/jumpstarter-cli/jumpstarter_cli/config_client.py
  • packages/jumpstarter-cli-driver/jumpstarter_cli_driver/driver.py
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py
  • packages/jumpstarter/jumpstarter/config/exporter.py
  • packages/jumpstarter-cli-common/jumpstarter_cli_common/print.py
  • packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py
  • packages/jumpstarter/jumpstarter/config/client.py
  • packages/jumpstarter/jumpstarter/client/grpc.py
🧰 Additional context used
🪛 Pylint (3.3.7)
packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py

[refactor] 98-101: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 103-106: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)

⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: build
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)
  • GitHub Check: pytest-matrix (macos-15, 3.13)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
  • GitHub Check: pytest-matrix (macos-15, 3.11)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: e2e

Comment on lines +110 to +126
def rich_add_rows(self, table):
selectors = []
for label in self.spec.selector.match_labels:
selectors.append(f"{label}:{str(self.spec.selector.match_labels[label])}")
table.add_row(
self.metadata.name,
self.spec.client.name if self.spec.client is not None else "",
",".join(selectors) if len(selectors) > 0 else "*",
self.status.exporter.name if self.status.exporter is not None else "",
self.spec.duration,
"Ended" if self.status.ended else "InProgress",
self.get_reason(),
self.status.begin_time if self.status.begin_time is not None else "",
self.status.end_time if self.status.end_time is not None else "",
time_since(self.metadata.creation_timestamp),
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

None values will crash Rich – coerce to empty strings
rich.table.Table.add_row() expects only str / RichRenderable instances.
self.spec.duration can be None, causing TypeError: unsupported operand type(s) for +: 'NoneType' and 'str' when Rich tries to concatenate. Apply the same safeguard used for begin_time/end_time.

-            self.spec.duration,
+            self.spec.duration or "",

While you’re here, the selector list can be built more idiomatically:

selectors = [f"{k}:{v}" for k, v in self.spec.selector.match_labels.items()]
🤖 Prompt for AI Agents
In packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py around lines
110 to 126, the call to table.add_row passes self.spec.duration which can be
None, causing a TypeError in Rich. Fix this by coercing self.spec.duration to an
empty string if it is None, similar to how begin_time and end_time are handled.
Also, refactor the selectors list construction to use a list comprehension:
replace the for loop with selectors = [f"{k}:{v}" for k, v in
self.spec.selector.match_labels.items()].

@NickCao NickCao merged commit cab71ed into main Jun 18, 2025
18 checks passed
@NickCao NickCao deleted the output-mode-new branch June 18, 2025 13:33
@coderabbitai coderabbitai Bot mentioned this pull request Jul 14, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Jul 21, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Oct 13, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants