Black: Error Path handling: `ValueError: '//src' does not start with '/'`

Created on 26 Aug 2020  ·  4Comments  ·  Source: psf/black

This happens within a docker container running at the root level.

For context:

root@2d592a60ac50:/# echo $PWD
/

root@2d592a60ac50:/# ls -l src/lib3to6/
total 160
-rw-r--r-- 1 root root   428 Aug 26 17:34 __init__.py
-rwxr-xr-x 1 root root  4181 Aug 26 17:34 __main__.py
...

root@2d592a60ac50:/# /opt/conda/envs/lib3to6_py38/bin/black --version
black, version 20.8b1

root@2d592a60ac50:/# /opt/conda/envs/lib3to6_py38/bin/python --version
Python 3.8.5

root@2d592a60ac50:/# uname -a
Linux 2d592a60ac50 5.4.0-42-generic #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020 x86_64 GNU/Linux

When I run black src/ I get this error.

root@2d592a60ac50:/# /opt/conda/envs/lib3to6_py38/bin/black src/
Traceback (most recent call last):
  File "/opt/conda/envs/lib3to6_py38/bin/black", line 8, in <module>
    sys.exit(patched_main())
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/black/__init__.py", line 6607, in patched_main
    main()
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/click/decorators.py", line 21, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/black/__init__.py", line 528, in main
    sources = get_sources(
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/black/__init__.py", line 604, in get_sources
    sources.update(
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/black/__init__.py", line 5868, in gen_python_files
    normalized_path = normalize_path_maybe_ignore(child, root, report)
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/site-packages/black/__init__.py", line 5835, in normalize_path_maybe_ignore
    normalized_path = path.resolve().relative_to(root).as_posix()
  File "/opt/conda/envs/lib3to6_py38/lib/python3.8/pathlib.py", line 904, in relative_to
    raise ValueError("{!r} does not start with {!r}"
ValueError: '//src/lib3to6' does not start with '/'

It works fine if I run it with the absolute path black /src/.

root@2d592a60ac50:/# /opt/conda/envs/lib3to6_py38/bin/black /src/
reformatted /src/lib3to6/__init__.py
reformatted /src/lib3to6/fixer_base.py
...
All done! ✨ 🍰 ✨
16 files reformatted, 1 file left unchanged.

Editing the local file, I see these values in the function:

root: PosixPath('/')
path: PosixPath('src/lib3to6')
path.resolve(): PosixPath('//src/lib3to6')

I feel very stupid saying this, but this may be an issue with the pathlib.Path.resolve function. You may nonetheless wish to implement a workaround by calling path.absolute() first:

root@2d592a60ac50:/# /opt/conda/envs/lib3to6_py38/bin/ipython
Python 3.8.5 | packaged by conda-forge | (default, Aug 21 2020, 18:21:27)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.17.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from pathlib import Path

In [2]: Path("src")
Out[2]: PosixPath('src')

In [3]: Path("src").resolve()
Out[3]: PosixPath('//src')

In [4]: Path("src").resolve().absolute()
Out[4]: PosixPath('//src')

In [5]: Path("src").absolute().resolve()
Out[5]: PosixPath('/src')

In [6]: root = Path("/")

In [7]: Path("src").absolute().resolve().relative_to(root)
Out[7]: PosixPath('src')
bug

Most helpful comment

Related python issue: https://bugs.python.org/issue33660. Whatever the WA will be, it might be worth mentioning that in a comment.

Last time Łukasz made the following WA: 75d2af2e3a0d0cf85b1e0c510c626d1ee1938074. This case certainly craves for a test.

All 4 comments

I see the Path.absolute() function is undocumented and the alternative is to use this Path.cwd(). So perhaps something like this:

def normalize_path_maybe_ignore(
    path: Path, root: Path, report: "Report"
) -> Optional[str]:
    """Normalize `path`. May return `None` if `path` was ignored.

    `report` is where "path ignored" output goes.
    """
    try:
        abspath = path if path.is_absolute() else Path.cwd() / path
        normalized_path = abspath.resolve().relative_to(root).as_posix()
    except OSError as e:
        report.path_ignored(path, f"cannot be read because {e}")
        return None

Related python issue: https://bugs.python.org/issue33660. Whatever the WA will be, it might be worth mentioning that in a comment.

Last time Łukasz made the following WA: 75d2af2e3a0d0cf85b1e0c510c626d1ee1938074. This case certainly craves for a test.

Sigh, that's frustrating. Thank you for jumping in @mbarkhau. I'll take care of BPO-33660 but for the time being we'll need an internal workaround. Care to add a PR to Black for that?

Would be happy to. I'll go forward with the above change and see if I can add a test.

Was this page helpful?
0 / 5 - 0 ratings