Darker: Incremental Python Code Formatter
Darker (version 3.0.0) is a Python utility that applies code formatting (using tools like Black, Ruff, isort, Flynt, and pyupgrade) only to regions of Python files that have changed since the last Git commit. This allows for gradual style unification in existing projects without large, disruptive formatting commits. It is actively maintained with regular releases.
Common errors
-
Command 'darker' not found
cause Darker is not installed or not available in the system's PATH. This can happen if installed in a virtual environment that isn't activated, or if the `scripts` directory isn't in PATH.fixEnsure Darker is installed (`pip install darker`) and your virtual environment is activated, or use `python -m darker` to invoke it directly. -
Darker found files that need reformatting. Would format the following files:
cause This is not an error but an informational message, typically when running `darker` in `--check` or `--diff` mode, indicating that changes *would* be applied.fixIf you want Darker to apply the formatting, remove the `--check` or `--diff` flag. If you want to accept the current state, commit your code and then run `darker` again to confirm no new changes are detected. -
Error: Black is not installed. Install it with `pip install 'darker[black]'`
cause Since Darker 3.0.0, Black is no longer a default dependency. Darker attempts to run Black but cannot find the `black` executable or module.fixInstall Black as an extra for Darker: `pip install 'darker[black]'`, or install Black separately: `pip install black`. -
DeprecationWarning: The Black option 'skip_string_normalization' in section [tool.darker] is deprecated...
cause You are using an older configuration for Black options within `[tool.darker]` in your `pyproject.toml` which is no longer supported in Darker 3.0.0+.fixMove `skip_string_normalization` (and `skip_magic_trailing_comma` if used) from the `[tool.darker]` section to the `[tool.black]` section in your `pyproject.toml`. -
error: cannot stat 'non_existent_file.py': No such file or directory
cause Darker was instructed to format a file or directory that does not exist in the specified path.fixVerify the file or directory path provided to Darker. Ensure there are no typos and the path is correct relative to where you are running the command.
Warnings
- breaking In Darker 3.0.0, the Black configuration options `skip_string_normalization` and `skip_magic_trailing_comma` are no longer supported under the `[tool.darker]` section in `pyproject.toml`. These options should now be configured directly under `[tool.black]` as per Black's configuration.
- breaking The `--lint` / `-L` command-line option for baseline linting was removed in Darker 3.0.0. This functionality has been moved to the separate `Graylint` package.
- breaking Black, the default formatter, is no longer installed by default with `pip install darker` since version 3.0.0. If you intend to use Black, you must install it explicitly.
- gotcha Darker accesses internals of Black, Ruff, isort, and Flynt, which can lead to compatibility issues with newer versions of these tools. It is recommended to use the compatible release (`~=`) version specifier for Darker and regularly check release notes.
- gotcha When using Darker as a `pre-commit` hook, issues can arise with `git merge-base` or incorrect revision comparisons. Explicitly setting the `--revision` flag (e.g., `--revision :PRE-COMMIT:`) or ensuring `PRE_COMMIT_FROM_REF`/`PRE_COMMIT_TO_REF` environment variables are correctly set might be necessary.
Install
-
pip install darker -
pip install 'darker[black]' -
pip install 'darker[ruff]' -
pip install 'darker[isort]'
Quickstart
# First, ensure you have a Git repository initialized and a Python file with changes
# Example setup:
# mkdir my_project && cd my_project && git init
# echo "print ( 'Hello, world' )" > my_file.py
# git add my_file.py && git commit -m "Initial commit"
# echo "def foo ( ):\n pass\nprint ( 'Another line' )" >> my_file.py
# Format only the modified lines in 'my_file.py'
# Requires black to be installed, e.g., pip install 'darker[black]'
import subprocess
import os
def run_darker(command):
try:
result = subprocess.run(command, capture_output=True, text=True, check=True)
print(result.stdout)
if result.stderr:
print(f"Stderr: {result.stderr}")
except subprocess.CalledProcessError as e:
print(f"Command failed with exit code {e.returncode}\nStdout: {e.stdout}\nStderr: {e.stderr}")
# Assuming you are in a git repository with changes in my_file.py
# This will reformat the added/modified lines in my_file.py
# For this example to be runnable, ensure 'darker' and 'black' are installed and a Git repo exists.
# To see an effect, modify my_file.py after an initial commit:
# echo "def some_func ( ):\n x = 1" >> my_file.py
# then run `python -m darker my_file.py`
print("Running darker on 'my_file.py'...")
# Use python -m darker to ensure it runs from the correct environment
run_darker(['python', '-m', 'darker', 'my_file.py'])
print("\nShowing the diff without applying changes (dry run):")
run_darker(['python', '-m', 'darker', '--diff', 'my_file.py'])
print("\nApplying darker with isort on 'my_file.py' (if isort installed):")
run_darker(['python', '-m', 'darker', '--isort', 'my_file.py'])