Skip to content

[2.7] bpo-32539: Fix OSError for os.listdir for extended paths on Windows#5169

Merged
serhiy-storchaka merged 1 commit intopython:2.7from
asottile:bpo-32539_listdir-windows-27-deep
Jan 15, 2018
Merged

[2.7] bpo-32539: Fix OSError for os.listdir for extended paths on Windows#5169
serhiy-storchaka merged 1 commit intopython:2.7from
asottile:bpo-32539_listdir-windows-27-deep

Conversation

@asottile
Copy link
Contributor

@asottile asottile commented Jan 12, 2018

Copy link
Member

Choose a reason for hiding this comment

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

Quote \\?\ with double backticks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done!

Copy link
Member

Choose a reason for hiding this comment

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

Do WinCE or OS/2 support such path syntax?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't actually have access to either of those environments -- is there an easy way I can check?

Copy link
Member

Choose a reason for hiding this comment

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

Does this directory exist? What if run python -m test -m test_listdir_extended_length_path test_os?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it would crash otherwise, it's set up as part of this code:

def setUp(self):
self.files = []
os.mkdir(test_support.TESTFN)

Copy link
Member

Choose a reason for hiding this comment

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

Does it matter if the directory empty? What if other files are left after other tests? Is it worth to test non-empty directory?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe the setUp / tearDown ensure this is empty, the contents of the directory don't actually matter, just that it exists and that the listdir(...) call does not crash. I added the assertion so it looks less like a useless test :)

@asottile asottile force-pushed the bpo-32539_listdir-windows-27-deep branch from 2913561 to 12c92ef Compare January 12, 2018 18:46
@asottile
Copy link
Contributor Author

@serhiy-storchaka

Did some research!

os/2 does not support this:

I spent hours trying to get a working windows CE emulator with some amount of command prompt and failed -- I've got no idea how the file system works there

@serhiy-storchaka
Copy link
Member

In Python 3 there is a special test for this: Win32ListdirTests.test_listdir_extended_path. Do you mind to backport it to 2.7?

Interesting that Unicode paths are handled correctly.

@asottile asottile force-pushed the bpo-32539_listdir-windows-27-deep branch 2 times, most recently from 390c20f to 354beaf Compare January 15, 2018 17:52
@asottile asottile force-pushed the bpo-32539_listdir-windows-27-deep branch from 354beaf to 0555344 Compare January 15, 2018 17:56
@asottile
Copy link
Contributor Author

Backported the tests!

Had to make these patches for compatibility:

--- py3	2018-01-15 09:58:09.123788000 -0800
+++ py2	2018-01-15 09:57:15.973225999 -0800
@@ -21,27 +21,29 @@
     def test_listdir_no_extended_path(self):
         """Test when the path is not an "extended" path."""
         # unicode
+        fs_encoding = sys.getfilesystemencoding()
         self.assertEqual(
-                sorted(os.listdir(support.TESTFN)),
-                self.created_paths)
+                sorted(os.listdir(support.TESTFN.decode(fs_encoding))),
+                [path.decode(fs_encoding) for path in self.created_paths])
 
         # bytes
         self.assertEqual(
                 sorted(os.listdir(os.fsencode(support.TESTFN))),
-                [os.fsencode(path) for path in self.created_paths])
+                self.created_paths)
 
     def test_listdir_extended_path(self):
         """Test when the path starts with '\\\\?\\'."""
         # See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
         # unicode
-        path = '\\\\?\\' + os.path.abspath(support.TESTFN)
+        fs_encoding = sys.getfilesystemencoding()
+        path = u'\\\\?\\' + os.path.abspath(support.TESTFN.decode(fs_encoding))
         self.assertEqual(
                 sorted(os.listdir(path)),
-                self.created_paths)
+                [path.decode(fs_encoding) for path in self.created_paths])
 
         # bytes
-        path = b'\\\\?\\' + os.fsencode(os.path.abspath(support.TESTFN))
+        path = b'\\\\?\\' + os.path.abspath(support.TESTFN)
         self.assertEqual(
                 sorted(os.listdir(path)),
-                [os.fsencode(path) for path in self.created_paths])
+                self.created_paths)

@serhiy-storchaka serhiy-storchaka added the type-bug An unexpected behavior, bug, or error label Jan 15, 2018
@serhiy-storchaka serhiy-storchaka changed the title bpo-32539: Fix OSError for os.listdir for deep paths on windows [2.7] bpo-32539: Fix OSError for os.listdir for extended paths on Windows Jan 15, 2018
@serhiy-storchaka serhiy-storchaka merged commit 27f32e9 into python:2.7 Jan 15, 2018
@asottile asottile deleted the bpo-32539_listdir-windows-27-deep branch January 15, 2018 21:39
@eryksun
Copy link
Contributor

eryksun commented Jan 15, 2018

"Interesting that Unicode paths are handled correctly."

That would have gone unfixed for all of a day at most. It's extremely rare to use a non-Unicode extended path. It can help to get around some quirks of the DOS namespace, such as DOS devices and files ending with dots and trailing spaces, but such names should be avoided in general anyway. The primary reason most people use extended paths is to avoid the (emulated DOS) MAX_PATH limit. MSDN clearly says this case is only supported with Unicode paths. Prior to Windows 8, ANSI (bytes) paths are definitely limited to MAX_PATH, extended or not. With Windows 8+ that's no longer the case, but the change is undocumented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type-bug An unexpected behavior, bug, or error

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants