Skip to content

Bug: _is_external_module misclassifies editable-installed project packages as third-party, skipping all tests #1

Description

@danqi437

Bug: Editable-install project packages are misclassified as third-party dependencies

Description

When a project is installed in editable mode (pip install -e . / uv sync), the top-level package name (e.g. feddb) appears in
the installed-packages list. _is_external_module() checks _installed_packages before checking project source files, so the
project itself is incorrectly classified as a third-party dependency.

This causes all from myproject.xxx import ... imports to be skipped during dependency analysis, resulting in an empty
dependency graph and all tests being skipped.

Reproduction

Any project installed in editable mode

git clone
cd
pip install -e .
pip install pytest-depper

Make a change on a branch

git checkout -b test-branch

... modify some source file ...

git add . && git commit -m "test change"

pytest --depper --depper-base-branch=origin/main

Expected: Tests that depend on the changed file are selected and run.

Actual:
Depper: Found N changed files
Depper: No tests affected by these changes
Deselecting all tests. This may indicate missing test coverage.

All tests are skipped.

Root Cause

In pytest_depper/analyzer.py, _is_external_module() checks in this order:

def _is_external_module(self, module_name: str) -> bool:
# 1. stdlib → external ✅ correct
if module_name in sys.stdlib_module_names:
return True

  # 2. installed package → external  ❌ BUG: editable-installed project matches here!
  if module_name.lower() in self._installed_packages:
      return True

  # 3. project source → internal  ⚠️  never reached for editable-installed packages
  if any(f.startswith(module_name) for f in self._python_files):
      return False

  return True

For an editable-install project, step 2 returns True before step 3 is ever reached.

Suggested Fix

Swap the check order — project source files first, then installed packages:

def _is_external_module(self, module_name: str) -> bool:
# 1. stdlib → external
if module_name in sys.stdlib_module_names:
return True

  # 2. project source → internal (check BEFORE installed packages)
  # Editable-installs put the project in _installed_packages,
  # but it is still project source code, not a third-party dependency.
  if any(f.startswith(module_name) for f in self._python_files):
      return False

  # 3. installed package → external
  if module_name.lower() in self._installed_packages:
      return True

  return True

Environment

  • Python 3.11
  • pytest-depper 0.2.0
  • Project installed via uv sync (editable mode)
  • Ubuntu 22.04

Workaround

We are currently applying a patch after pip install pytest-depper in our CI:

DEPPER_ANALYZER="$(python -c "import pytest_depper, os; print(os.path.join(os.path.dirname(pytest_depper.file),
'analyzer.py'))")"
patch -p1 -d "$(dirname "$DEPPER_ANALYZER")/.." < depper-editable-install.patch

Patch:
--- a/pytest_depper/analyzer.py
+++ b/pytest_depper/analyzer.py
@@ -287,14 +287,16 @@
if hasattr(sys, "stdlib_module_names") and module_name in sys.stdlib_module_names:
return True

  •    # Check if it's a file in our project BEFORE installed packages.
    
  •    # An editable-install (pip install -e .) puts the project in the
    
  •    # installed-packages list, but it is still project source code.
    
  •    if any(f.startswith(module_name) for f in self._python_files):
    
  •        return False
    
  •    # Check if it's an installed third-party package
       if module_name.lower() in self._installed_packages:
           return True
    
  •    # Check if it's a file in our project
    
  •    if any(f.startswith(module_name) for f in self._python_files):
    
  •        return False
    
  •    # Assume it's external if not found in project
       return True
    

Thanks for the great tool! This fix would make depper work correctly out-of-the-box for any editable-install project.


Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions