Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when using --stdin-filename , cannot override auto-found project root with --config #4232

Open
pmolodo opened this issue Feb 14, 2024 · 2 comments
Labels
T: bug Something isn't working

Comments

@pmolodo
Copy link

pmolodo commented Feb 14, 2024

Describe the bug

When using stdin + --stdin-filename, black will always set it's project root to the directory it auto-finds. The docs imply that you can override this by using --config:

By default Black looks for pyproject.toml containing a [tool.black] section starting from the common base directory of all files and directories passed on the command line. If it’s not there, it looks in parent directories. It stops looking when it finds the file, or a .git directory, or a .hg directory, or the root of the file system, whichever comes first.
...
You can also explicitly specify the path to a particular file that you want with --config. In this situation Black will not look for any other file.

However, in practice, specifying --config seems to make no difference, and it always uses the auto-found directory.

This is problematic when working with .git submodules, as there does not seem to be an easy way to enable formatting for the top-level repository (which you control), and disable it for the subrepos / submodules (which you do NOT control), without making edits in the repos you do not control.

To Reproduce

Our test directory structure will look like:

black-stdin-test/
|- pyproject.toml
|- submodule/
|   |- .git/
|   |- testfile.py

To create this, and run black, execute this .sh script:

#!/bin/bash

mkdir -p black-stdin-test
cd black-stdin-test
mkdir -p submodule/.git
echo "foo=7" > submodule/testfile.py
echo '[tool.black]
verbose = true
force-exclude = "submodule"
' > pyproject.toml


echo "================================"
echo "This will format the file, when it should be excluded"
echo "================================"
echo cat ${PWD}/submodule/testfile.py '|' black --stdin-filename ${PWD}/submodule/testfile.py --config ${PWD}/pyproject.toml - '>' /dev/null
cat ${PWD}/submodule/testfile.py | black --stdin-filename ${PWD}/submodule/testfile.py --config ${PWD}/pyproject.toml - > /dev/null
echo
echo

echo "================================"
echo "This won't format the file, as expected"
echo "================================"
echo black  .
black .

This will give this output:

================================
This will format the file, when it should be excluded
================================
cat /black-stdin-test/submodule/testfile.py | black --stdin-filename /black-stdin-test/submodule/testfile.py --config /black-stdin-test/pyproject.toml - > /dev/null
Identified `/black-stdin-test/submodule` as project root containing a .git directory.
Using configuration in '/black-stdin-test/pyproject.toml'.
verbose: True
force_exclude: submodule
Found input source: "__BLACK_STDIN_FILENAME__/black-stdin-test/submodule/testfile.py"
reformatted /black-stdin-test/submodule/testfile.py

All done! ✨ 🍰 ✨
1 file reformatted.


================================
This won't format the file, as expected
================================
black .
Identified `/black-stdin-test` as project root containing a pyproject.toml.
Using configuration from project root.
verbose: True
force_exclude: submodule
Found input source directory: "/black-stdin-test"
/black-stdin-test/submodule ignored: matches the --force-exclude regular expression
No Python files are present to be formatted. Nothing to do 😴

Expected behavior

Given the docs quoted above, I would expect the --config flag to set the project root, and allow excluding of the submodule directory.

If the current behavior is intended, then at minimum I think the docs should be clarified... and ideally there should be a way to either explicitly set the project root. (Ideally, within a pyproject.toml, you could set an option to always mark it's parent folder as the project root, so the exclude paths it contains would always be relative to "itself").

Environment

  • Black's version: black, 24.2.1.dev1+gd1d4fc5 (running from latest dev branch)
  • OS and Python version: Linux (Ubuntu 20.04)/Python 3.10.9
@pmolodo pmolodo added the T: bug Something isn't working label Feb 14, 2024
@pmolodo
Copy link
Author

pmolodo commented Feb 14, 2024

So, for those looking for a workaround for vscode (where I encountered this), I found that by adding an additional file to be formatted, I can control the project directory it sets, since it will use the "common base directory of all files". I then also add this to the --force-exclude. It's very hacky, but it works.

Of course, this means you have to do this from within vscode's settings, not a pyproject.toml. In your .vscode/settings.json, it looks like this:

{
    "editor.formatOnSave": true,
    "editor.formatOnSaveMode": "file",
    "python.formatting.provider": "black",
    "black-formatter.args": [
        "${workspaceFolder}/.gitignore",
        "--force-exclude",
        "\\.gitignore\n|submodule"
    ]
}

@huntedman
Copy link

Doesn't work for me :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants