Skip to content

feat: add pip installation support with optional torch-scatter dependency#28

Open
liu-687 wants to merge 2 commits into
deepmodeling:mainfrom
liu-687:feat/pip-install-support
Open

feat: add pip installation support with optional torch-scatter dependency#28
liu-687 wants to merge 2 commits into
deepmodeling:mainfrom
liu-687:feat/pip-install-support

Conversation

@liu-687

@liu-687 liu-687 commented Jun 29, 2026

Copy link
Copy Markdown

Summary

Make dftio pip-installable by converting torch-scatter from a hard dependency into an optional extra. This allows pip install dftio to work out of the box for all core functionality.

Background

torch-scatter requires pre-compiled wheels from data.pyg.org that are not reliably available on PyPI. It is only used in one file (dftio/op/grid_int.py) for LDOS (Local Density of States) calculations. All other features (parsing, data structures, CLI, band plotting) work without it.

Changes

  • dftio/op/grid_int.py: Replace module-level torch_scatter import with lazy import inside integrate() method, with helpful error message guiding users to install dftio[scatter]
  • pyproject.toml: Move torch-scatter from core dependencies to [project.optional-dependencies] under scatter extra; add full and dev extras for pip users
  • New: requirements.txt, requirements-dev.txt, requirements-full.txt for pip-based workflows
  • test/test_grid_int.py & test/test_ldos.py: Add needs_scatter pytest skip marker so scatter-dependent tests are gracefully skipped when torch-scatter is not installed
  • .github/workflows/test.yml: Update uv sync to include --extra scatter so scatter tests continue to run in CI
  • install.sh: Add --extra scatter flag to uv sync command
  • README.md & docs/installation.md: Replace "coming soon" placeholder with actual pip installation instructions

How to Test

# Core install (no scatter needed)
pip install .
python -c "from dftio.op import SingleGridIntegrator; from dftio.calc.ldos import LDOS; print(\"OK\")"

# Full install with scatter
pip install "dftio[scatter]" -f https://data.pyg.org/whl/torch-2.5.0+cpu.html

# Tests
uv sync --group dev --extra scatter
uv run pytest -v -m "not integration"

Breaking Change

torch-scatter is no longer installed by default. Users who need LDOS calculations must install with pip install "dftio[scatter]" or use requirements-full.txt. When calling integrate() without scatter installed, users will see a helpful error message with installation instructions.

Summary by CodeRabbit

  • New Features

    • Added clearer installation options for standard, scatter-enabled, full, and CUDA setups.
    • Introduced optional support for scatter-based functionality during install.
  • Bug Fixes

    • Improved error messaging when scatter support is needed but not installed.
    • Tests now skip scatter-dependent checks when that optional package isn’t available, reducing false failures.
  • Documentation

    • Expanded setup instructions with concrete pip and requirements-file examples.
    • Clarified which features require scatter support and which work without it.

…ency

- Move torch-scatter from core dependencies to optional extra 'scatter'
- Add lazy import in grid_int.py with helpful error message for LDOS users
- Add conditional pytest skip markers for scatter-dependent tests
- Create requirements.txt / requirements-dev.txt / requirements-full.txt
- Update CI workflow to install scatter extra
- Update README and docs with pip installation instructions

BREAKING CHANGE: torch-scatter is no longer installed by default.
Users needing LDOS calculations should install with pip install dftio[scatter]
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@liu-687, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 35 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7e58d36c-c5ab-45fd-9a5c-6e65049ebd6c

📥 Commits

Reviewing files that changed from the base of the PR and between fc7f56e and f706c72.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • README.md
  • dftio/op/grid_int.py
  • docs/installation.md
  • install.sh
  • pyproject.toml
  • requirements-full.txt
  • test/test_grid_int.py
📝 Walkthrough

Walkthrough

torch-scatter is moved from a required dependency to an optional scatter extra in pyproject.toml and new requirements files. The import in grid_int.py is deferred to call time with a helpful error on failure. Tests conditionally skip when torch_scatter is absent, and CI, install.sh, README, and docs are updated to match.

Changes

Make torch-scatter an optional extra

Layer / File(s) Summary
Package metadata and requirements files
pyproject.toml, requirements.txt, requirements-dev.txt, requirements-full.txt
torch-scatter==2.1.2 removed from main deps; scatter, full, and dev optional extras defined; core and full requirements files populated with pinned deps.
Lazy import in grid_int.py
dftio/op/grid_int.py
Top-level scatter_sum import removed; SingleGridIntegrator.integrate() now imports scatter_sum locally and raises ImportError with install instructions when torch_scatter is absent.
Conditional test skipping and CI
test/test_grid_int.py, test/test_ldos.py, .github/workflows/test.yml, install.sh
Both test modules detect torch_scatter availability and apply a needs_scatter skip marker; CI uv sync and install.sh add --extra scatter.
Docs and README
README.md, docs/installation.md
"Using pip" sections expanded with concrete install commands for core, scatter, full, and CUDA variants; note added that dftio[scatter] is only required for dftio.calc.ldos.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: pip installation support with torch-scatter made optional.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
test/test_grid_int.py (1)

55-80: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add one test for the no-scatter error path.

With @needs_scatter, the only integrate() test is skipped exactly where this PR changes behavior, so the new ImportError contract/message is never asserted. A small test that forces the import to fail and checks the raised message would lock down the new optional-dependency behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/test_grid_int.py` around lines 55 - 80, The current `test_integrate`
coverage only runs when scatter support is available, so it never exercises the
new optional-dependency failure path in `SingleGridIntegrator.integrate`. Add a
separate test that simulates scatter being unavailable, invokes `integrate()` on
`SingleGridIntegrator`, and asserts that an `ImportError` is raised with the
expected message. Reuse the existing `SingleGridIntegrator` setup and keep the
new test focused on the no-scatter branch so the behavior is locked down even
when `@needs_scatter` skips the happy-path test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@dftio/op/grid_int.py`:
- Around line 36-42: The ImportError handling in the grid integration path drops
the original exception context. Update the `except ImportError` block in
`grid_int.py` to bind the exception as `err` and re-raise the new `ImportError`
from that original error so the traceback preserves the missing-dependency
cause.
- Around line 37-41: The ImportError message in grid_int.py hardcodes the
torch-2.5.0+cpu wheel hint, which sends users to the wrong install path on CUDA
setups. Update the exception text in the grid integration import guard to prefer
the existing dftio[scatter] / install guide guidance or derive the correct wheel
selector dynamically, and make sure the raised ImportError in the relevant
import block is chained with from err so the original cause is preserved.

In `@docs/installation.md`:
- Around line 52-54: The installation docs currently describe the full extra as
including both scatter and dev tools, but the actual extra definition in
pyproject.toml only maps full to dftio[scatter]. Update the wording in
docs/installation.md so it matches the package metadata, or change the full
extra in pyproject.toml if dev tools are meant to be included; use the full
extra definition and the pip install "dftio[full]" example as the references to
keep both sources consistent.

In `@install.sh`:
- Line 50: The `uv sync` invocation in `install.sh` is passing the Python path
from `$(which python)` unquoted, which can break when the path contains spaces.
Update the existing `uv sync` command to quote the Python path result while
keeping the current lookup approach, so the `--python` argument is always passed
as a single value.

In `@pyproject.toml`:
- Line 39: The `full` extra in pyproject.toml is inconsistent with the README
description because it only includes `dftio[scatter]` while the docs say it also
covers dev tools. Update the dependency definition in the `full` extra to
include `dftio[dev]` as well, or change the README wording to match the actual
`full` set; make the definition and documentation consistent using the `full`
extra symbol and the related `dev`/`scatter` extras.

In `@README.md`:
- Around line 51-53: The README install note for the full extra is inconsistent
with the package definition in pyproject.toml. Update the description next to
the dftio[full] install example to match the actual extra behavior, or change
the full extra definition in pyproject.toml if it is meant to include dev as
well; use the README install snippet and the full extra entry as the main points
of reference.

---

Nitpick comments:
In `@test/test_grid_int.py`:
- Around line 55-80: The current `test_integrate` coverage only runs when
scatter support is available, so it never exercises the new optional-dependency
failure path in `SingleGridIntegrator.integrate`. Add a separate test that
simulates scatter being unavailable, invokes `integrate()` on
`SingleGridIntegrator`, and asserts that an `ImportError` is raised with the
expected message. Reuse the existing `SingleGridIntegrator` setup and keep the
new test focused on the no-scatter branch so the behavior is locked down even
when `@needs_scatter` skips the happy-path test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3ba4f618-1b45-4092-a65d-9fee62f3bc67

📥 Commits

Reviewing files that changed from the base of the PR and between c9d128f and fc7f56e.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • .github/workflows/test.yml
  • README.md
  • dftio/op/grid_int.py
  • docs/installation.md
  • install.sh
  • pyproject.toml
  • requirements-dev.txt
  • requirements-full.txt
  • requirements.txt
  • test/test_grid_int.py
  • test/test_ldos.py

Comment thread dftio/op/grid_int.py Outdated
Comment thread dftio/op/grid_int.py Outdated
Comment thread docs/installation.md
Comment thread install.sh Outdated
Comment thread pyproject.toml Outdated
Comment thread README.md
…stency, and test coverage

- Use raise ImportError(...) from err to preserve original exception context
- Rework error message to avoid hardcoding CPU wheel URL; prioritize dftio[scatter] extra
- Fix full extra to include both scatter and dev, matching documentation
- Update requirements-full.txt to include dev dependencies
- Quote /Users/liu687/anaconda3/bin/python in install.sh to handle paths with spaces
- Add test_integrate_without_scatter_raises_error to cover no-scatter path
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