Skip to content

Conversation

@srir
Copy link

@srir srir commented Dec 9, 2025

Summary

Previously, auto-uv only looked for project markers (pyproject.toml, .venv, uv.lock) starting from the current working directory. This caused issues when running scripts from a different directory:

cd /some/dir
python /path/to/project/script.py  # auto-uv wouldn't detect the project

This change adds script-path-based detection:

  1. First try to find project root from the script's directory
  2. Fall back to CWD for backwards compatibility

Changes

  • Extracted _find_project_root() helper function that walks up directories looking for project markers
  • Modified should_use_uv() to accept optional script_path parameter
  • Modified auto_use_uv() to pass the script path to should_use_uv()
  • Added comprehensive test for script-path detection

Use Case

This enables running Python scripts from any directory while still having auto-uv intercept and use uv run:

cd ~
python /path/to/my-project/scripts/do_something.py
# Now correctly detects /path/to/my-project/pyproject.toml

Test Plan

  • All existing tests pass
  • New test_script_path_detection test added and passing
  • Manual testing with real project directories

🤖 Generated with Claude Code

Summary by Sourcery

Detect uv projects based on the executed script’s directory, falling back to the current working directory for compatibility.

New Features:

  • Support project detection from the script path so auto-uv can intercept scripts run from outside the project directory.

Enhancements:

  • Extract a reusable helper to locate the project root by walking up from a starting directory.
  • Update auto-uv interception logic to pass the script path into project detection.

Tests:

  • Add comprehensive tests covering script-path-based project detection and project-root discovery from various directories.

Previously, auto-uv only looked for project markers (pyproject.toml, .venv,
uv.lock) starting from the current working directory. This caused issues when
running scripts from a different directory:

    cd /some/dir
    python /path/to/project/script.py  # auto-uv wouldn't detect the project

This change adds script-path-based detection:
1. First try to find project root from the script's directory
2. Fall back to CWD for backwards compatibility

This enables the use case of running Python scripts from any directory while
still having auto-uv intercept and use `uv run`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@sourcery-ai
Copy link

sourcery-ai bot commented Dec 9, 2025

Reviewer's Guide

Refactors project-root detection into a reusable helper and updates the auto-uv interception logic to prefer detecting projects from the script’s directory (with CWD as fallback), along with tests verifying the new behavior and preserving existing path-normalization checks.

Sequence diagram for auto_uv interception using script_path and CWD fallback

sequenceDiagram
    actor User
    participant Python as PythonInterpreter
    participant AutoUV as auto_use_uv
    participant Should as should_use_uv
    participant Finder as _find_project_root

    User->>Python: python script.py
    Python->>AutoUV: auto_use_uv()

    AutoUV->>Python: inspect sys.argv / sys.path
    AutoUV->>AutoUV: resolve script_path

    AutoUV->>Should: should_use_uv(script_path)
    Should->>Should: check UV_RUN_ACTIVE
    Should->>Should: check AUTO_UV_DISABLE
    Should->>Python: subprocess.run("uv", "--version")
    Python-->>Should: uv available?
    Should->>Should: handle errors, maybe return False

    alt uv_available
        alt script_path_provided
            Should->>Finder: _find_project_root(script_dir)
            Finder-->>Should: project_root or None
        end

        alt no_project_root_from_script_dir
            Should->>Finder: _find_project_root(os_getcwd)
            Finder-->>Should: project_root or None
        end

        alt project_root_found
            Should-->>AutoUV: True
            AutoUV->>Python: set UV_RUN_ACTIVE
            AutoUV->>Python: exec uv run script
        else no_project_root_found
            Should-->>AutoUV: False
            AutoUV-->>Python: return without interception
        end
    else uv_not_available
        Should-->>AutoUV: False
        AutoUV-->>Python: return without interception
    end
Loading

Flow diagram for _find_project_root directory walk

flowchart TD
    start["Start with start_dir"] --> absdir["check_dir = abs(start_dir)"]
    absdir --> loop_start["For up to max_depth levels"]

    loop_start --> check_markers{"Does check_dir contain pyproject.toml or .venv or uv.lock?"}

    check_markers -->|Yes| found["Return check_dir as project_root"]
    check_markers -->|No| parent_step["parent = dirname(check_dir)"]

    parent_step --> reached_root{"Is parent == check_dir?"}
    reached_root -->|Yes| no_root["Break loop (filesystem root reached)"]
    reached_root -->|No| update_dir["check_dir = parent"]

    update_dir --> loop_start

    no_root --> return_none["Return None (no project markers found)"]

    style start fill:#e3f2fd,stroke:#1e88e5
    style found fill:#c8e6c9,stroke:#43a047
    style return_none fill:#ffcdd2,stroke:#e53935
Loading

File-Level Changes

Change Details Files
Introduce reusable project-root discovery helper and use it in uv interception logic, preferring script location over CWD.
  • Added _find_project_root(start_dir, max_depth=10) to walk up from a starting directory looking for pyproject.toml, .venv, or uv.lock and return the first directory containing any of these markers.
  • Refactored should_use_uv into should_use_uv(script_path=None), keeping all existing env/uv-availability checks but delegating project detection to _find_project_root.
  • Updated project detection logic to first attempt discovery from the script directory (when script_path is provided) and then fall back to the current working directory for backwards compatibility.
  • Simplified the final decision in should_use_uv to return whether a project_root was found.
src/auto_uv.py
Wire script path into auto-use flow so interception decisions are based on the script’s location.
  • Modified auto_use_uv to pass the resolved script_path into should_use_uv instead of calling it parameterless.
  • Preserved existing early-return behavior for standard library scripts while now enabling project detection based on non-CWD script paths.
src/auto_uv.py
Add and integrate tests verifying script-path-based project detection and its interaction with existing test harness.
  • Added test_script_path_detection() to construct a temporary project with pyproject.toml and an unrelated directory, then assert should_use_uv() behavior both with and without script_path, and validate _find_project_root from relevant directories.
  • Ensured environment variables (AUTO_UV_DISABLE, UV_RUN_ACTIVE) and working directory are saved and restored around the new test to avoid side effects.
  • Extended the manual test runner in test_path_normalization() to invoke test_script_path_detection and report its pass/fail status.
tests/test_auto_uv.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • The tests currently import and assert against the private helper _find_project_root; consider either testing this behavior only through should_use_uv/auto_use_uv or promoting _find_project_root to a public helper if you intend it to be part of the supported surface.
  • In test_script_path_detection, you're manually saving/restoring os.environ and calling os.environ.clear(), which is easy to get wrong and can interfere with other tests; using monkeypatch (or a similar fixture) to isolate env changes would make this safer and more readable.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The tests currently import and assert against the private helper `_find_project_root`; consider either testing this behavior only through `should_use_uv`/`auto_use_uv` or promoting `_find_project_root` to a public helper if you intend it to be part of the supported surface.
- In `test_script_path_detection`, you're manually saving/restoring `os.environ` and calling `os.environ.clear()`, which is easy to get wrong and can interfere with other tests; using `monkeypatch` (or a similar fixture) to isolate env changes would make this safer and more readable.

## Individual Comments

### Comment 1
<location> `tests/test_auto_uv.py:489` </location>
<code_context>
+            print(f"From unrelated dir, no script_path: should_use_uv = {result}")
+            assert result is False, "Should NOT detect project when CWD has no markers and no script_path"
+
+            # Test 2: From unrelated dir, should_use_uv(script_path) returns True
+            result = should_use_uv(script_path)
+            print(f"From unrelated dir, with script_path: should_use_uv = {result}")
</code_context>

<issue_to_address>
**suggestion (testing):** Add a test for the case where CWD is a project but the script_path points outside it

Currently this only asserts: (a) CWD has no markers and no script_path ⇒ False, and (b) CWD has no markers but script_path is inside a project ⇒ True. It would be valuable to also cover the case where CWD *is* a project dir but `script_path` points outside any project, to verify that CWD-based detection still applies and that a non-project `script_path` doesn’t override it. For example:

- create `project_dir` with markers
- `os.chdir(project_dir)`
- choose `script_path` in `unrelated_dir`
- assert `should_use_uv(script_path)` matches the intended behavior (likely `True`, or explicitly `False` if that’s the spec).

This will clearly document and lock in the precedence between script-based and CWD-based detection.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

print(f"From unrelated dir, no script_path: should_use_uv = {result}")
assert result is False, "Should NOT detect project when CWD has no markers and no script_path"

# Test 2: From unrelated dir, should_use_uv(script_path) returns True
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Add a test for the case where CWD is a project but the script_path points outside it

Currently this only asserts: (a) CWD has no markers and no script_path ⇒ False, and (b) CWD has no markers but script_path is inside a project ⇒ True. It would be valuable to also cover the case where CWD is a project dir but script_path points outside any project, to verify that CWD-based detection still applies and that a non-project script_path doesn’t override it. For example:

  • create project_dir with markers
  • os.chdir(project_dir)
  • choose script_path in unrelated_dir
  • assert should_use_uv(script_path) matches the intended behavior (likely True, or explicitly False if that’s the spec).

This will clearly document and lock in the precedence between script-based and CWD-based detection.

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.

1 participant