This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author ucodery
Recipients ucodery
Date 2021-10-20.22:54:44
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1634770485.18.0.358610816486.issue45545@roundup.psfhosted.org>
In-reply-to
Content
The way that contextlib.chdir currently restores the old working directory, an exception is raised if the program was already close to or beyond a system's PATH_MAX. The context manager has no issue crafting the path in __enter__ because os.getcwd() can return a path that is longer than PATH_MAX, but when used in __exit__ os.chdir() cannot use a path that long.

I think an __exit__ should be as cautious as possible to not raise as the exception can occur far away from where the context manager was created. Its also doesn't reflect the programmer actually using the context manager incorrectly as they might not have any control or care where the process was started, yet if it happened to already be at a deep path when launched, any use of chdir anywhere would cause exceptions.

I have tested this on macOS 11.13 using APFS but I am sure it would also fail on other macs and Linuxes. I don't know about Windows. Note I originally created this test as a patch to Lib/tests/test_contextlib.py but libregrtest uses os.getcwd() in its runner and that disrupts the traceback and misidentifies the cause of failure. Test file:

```python
import os
import shutil
from contextlib import chdir


def test_long_path():
    # NAME_MAX of 255
    long_filename = "_".join(["testdir"]*32)
    long_path_end = startingwd = os.getcwd()
    try:
        # I thought this would have to be 16, i.e. a path length over 4096, PATH_MAX
        # but seemingly just crossing 1050 is enough to fail
        for _ in range(4):
            os.mkdir(long_filename)
            os.chdir(long_filename)
            long_path_end = os.path.join(long_path_end, long_filename)
        os.mkdir(long_filename)
        long_path_end = os.path.join(long_path_end, long_filename)
        with chdir(long_filename):
            #self.assertEqual(os.getcwd(), long_path_end)
            assert os.getcwd() == long_path_end
            print("passed")
    finally:
        shutil.rmtree(os.path.join(startingwd, long_filename), ignore_errors=True)


test_long_path()
```

And output:
```
$ ./python.exe ./test_chdir.py
passed
Traceback (most recent call last):
  File "/Users/ucodery/git/cpython/./test_chdir.py", line 27, in <module>
    test_long_path()
    ^^^^^^^^^^^^^^^^
  File "/Users/ucodery/git/cpython/./test_chdir.py", line 19, in test_long_path
    with chdir(long_filename):
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ucodery/git/cpython/Lib/contextlib.py", line 781, in __exit__
    os.chdir(self._old_cwd.pop())
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 63] File name too long: '/Users/ucodery/git/cpython/testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir/testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir/testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir/testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir_testdir'
```
History
Date User Action Args
2021-10-20 22:54:45ucoderysetrecipients: + ucodery
2021-10-20 22:54:45ucoderysetmessageid: <1634770485.18.0.358610816486.issue45545@roundup.psfhosted.org>
2021-10-20 22:54:45ucoderylinkissue45545 messages
2021-10-20 22:54:45ucoderycreate