Skip to content

Add Tool.default_command() to eliminate duplication in CI steps and help messages#1088

Merged
nathanjmcdougall merged 8 commits intomainfrom
copilot/create-tool-default-command-method
Nov 5, 2025
Merged

Add Tool.default_command() to eliminate duplication in CI steps and help messages#1088
nathanjmcdougall merged 8 commits intomainfrom
copilot/create-tool-default-command-method

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Nov 5, 2025

The get_bitbucket_steps() methods across tool implementations contained significant duplication, repeating the same command strings used in help messages. This PR introduces Tool.default_command() to define commands once and enables a default get_bitbucket_steps() implementation.

Changes

Core Protocol Method

  • Added default_command() -> str to Tool protocol that returns backend-dependent command strings
  • Returns "uv run <tool> [args]" when uv backend is active with uv.lock present
  • Returns "<tool> [args]" for none backend or uv without lock file
  • Raises NoDefaultToolCommand exception by default for tools without commands (instead of returning None)

Custom Exception

  • Added NoDefaultToolCommand exception in src/usethis/errors.py for tools that don't have associated commands
  • Base get_bitbucket_steps() implementation uses try-except to handle tools without commands

Default Implementation

  • Added default get_bitbucket_steps() implementation in base Tool class that uses default_command()
  • Automatically generates appropriate Bitbucket pipeline steps with correct caching and anchors
  • Can be overridden for complex cases (e.g., pytest with multiple Python versions, Ruff with separate linter/formatter)

Tool Updates

Implemented default_command() in 5 tools:

  • CodespellTool: "codespell"
  • PyprojectFmtTool: "pyproject-fmt pyproject.toml"
  • DeptryTool: "deptry {src_dir}" (dynamic)
  • ImportLinterTool: "lint-imports"
  • PytestTool: "pytest"

Note: RuffTool was intentionally excluded as it doesn't have a single default command (has separate linter and formatter commands).

Refactored print_how_to_use() methods to use default_command() instead of duplicating command strings.

Code Reduction

Removed ~160 lines of duplicated get_bitbucket_steps() implementations from simple tools (CodespellTool, PyprojectFmtTool, DeptryTool, ImportLinterTool) that now inherit the default implementation.

Example

Before:

def print_how_to_use(self):
    if backend is BackendEnum.uv and is_uv_used():
        how_print("Run 'uv run codespell' to run the Codespell spellchecker.")
    else:
        how_print("Run 'codespell' to run the Codespell spellchecker.")

def get_bitbucket_steps(self):
    if backend is BackendEnum.uv:
        return [BitbucketStep(script=["uv run codespell"])]
    # ... duplicated command logic

After:

def default_command(self) -> str:
    backend = get_backend()
    if backend is BackendEnum.uv and is_uv_used():
        return "uv run codespell"
    return "codespell"

def print_how_to_use(self):
    cmd = self.default_command()
    how_print(f"Run '{cmd}' to run the Codespell spellchecker.")

# get_bitbucket_steps() now inherited from base class
Original prompt

This section details on the original issue you should resolve

<issue_title>Create a Tool.default_command method</issue_title>
<issue_description>To avoid duplication between (and within) get_bitbucket_steps methods for CI, and probably help messages, etc.

This would be backend dependent.

By default, it should return None, since not all tools have commands. Otherwise, return a string.

The individual tool implementations (Tool subclassses), for tools which associated with commands, should provide an implementation.

We should use the method anywhere where the default command is used, e.g. help messages, but certainly get_bitbucket_steps methods.</issue_description>

Comments on the Issue (you are @copilot in this section)

@nathanjmcdougall This will also enable default implementations for `get_bitbucket_steps` methods

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits November 5, 2025 10:39
…classes

Co-authored-by: nathanjmcdougall <18602289+nathanjmcdougall@users.noreply.github.com>
Co-authored-by: nathanjmcdougall <18602289+nathanjmcdougall@users.noreply.github.com>
Co-authored-by: nathanjmcdougall <18602289+nathanjmcdougall@users.noreply.github.com>
Copilot AI changed the title [WIP] Create Tool.default_command method to avoid duplication Add Tool.default_command() to eliminate duplication in CI steps and help messages Nov 5, 2025
…ning None

Co-authored-by: nathanjmcdougall <18602289+nathanjmcdougall@users.noreply.github.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Nov 5, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Nov 5, 2025

CodSpeed Performance Report

Merging #1088 will not alter performance

Comparing copilot/create-tool-default-command-method (ee1c148) with main (cd89644)1

Summary

✅ 2 untouched

Footnotes

  1. No successful run was found on main (99a5ffb) during the generation of this report, so cd89644 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@nathanjmcdougall nathanjmcdougall marked this pull request as ready for review November 5, 2025 19:21
@nathanjmcdougall nathanjmcdougall merged commit 73f05e1 into main Nov 5, 2025
20 checks passed
@nathanjmcdougall nathanjmcdougall deleted the copilot/create-tool-default-command-method branch November 5, 2025 19:21
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.

Create a Tool.default_command method

2 participants