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.

classification
Title: pathlib issues with Windows device paths
Type: behavior Stage: patch review
Components: Library (Lib), Windows Versions: Python 3.9, Python 3.8, Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: eryksun, paul.moore, pitrou, steve.dower, tim.golden, zach.ware
Priority: normal Keywords: patch

Created on 2018-06-18 22:40 by eryksun, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 8671 open python-dev, 2018-08-04 11:54
Messages (2)
msg319921 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2018-06-18 22:40
For \\?\ extended device paths, pathlib removes the trailing slash for the root directory if the device isn't UNC or a logical (A-Z) drive.

Correct:

    >>> str(Path('//?/UNC/'))
    '\\\\?\\UNC\\'

    >>> str(Path('//?/Z:/'))
    '\\\\?\\Z:\\'

Incorrect:

    >>> str(Path('//?/BootPartition/'))
    '\\\\?\\BootPartition'

    >>> str(Path('//?/Volume{}/'))
    '\\\\?\\Volume{}'

    >>> str(Path('//?/Global/Z:/'))
    '\\\\?\\Global\\Z:'

It keeps the trailing slash for some \\.\ paths, but not all.

Correct:

    >>> str(Path('//./BootPartition/'))
    '\\\\.\\BootPartition\\'

Incorrect:

    >>> str(Path('//./Global/Z:/'))
    '\\\\.\\Global\\Z:'

It adds a root directory to \\.\ device paths where none was specified. 

Incorrect:

    >>> str(Path('//./nul'))
    '\\\\.\\nul\\'

    >>> str(Path('//./PhysicalDrive0'))
    '\\\\.\\PhysicalDrive0\\'

    >>> str(Path('//./C:'))
    '\\\\.\\C:\\'

"\\\\.\\C:" refers to the volume device, whereas "\\\\.\\C:\\" is the root directory in the file system.

pathlib should parse \\?\ and \\.\ device paths the same way with respect to the drive and root. The difference in practice is only how Windows does (\\.\) or does not (\\?\) canonicalize the path. 

Additionally, pathlib fails to identify the drive correctly in these cases.

Incorrect:

    >>> Path('//?/Global/Z:/').drive
    '\\\\?\\'

    >>> Path('//?/BootPartition/Temp').drive
    '\\\\?\\'

Except for "UNC" and "Global" paths, the drive should be the first component after the local-device prefix. The "UNC" device also includes subsequent server and share components, if any. For the reserved "Global" symlink, it should look to the next component. For example, r'\\?\Global\UNC\server\share' is a drive. 

There's also the "GlobalRoot" symlink (or "Global\\GlobalRoot" to be pedantic), but that can't be handled generically.
msg337405 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2019-03-07 16:51
Eryk - I've got the PR ready as far as I'm concerned. Have you had a look to see if you're happy with its logic for these cases?
History
Date User Action Args
2022-04-11 14:59:01adminsetgithub: 78079
2021-03-22 01:00:39eryksunlinkissue39920 superseder
2020-04-17 17:59:50pitrousetversions: + Python 3.9
2019-03-07 16:51:20steve.dowersetmessages: + msg337405
2019-02-16 23:46:59cheryl.sabellasetversions: - Python 3.6
2018-08-04 11:54:17python-devsetkeywords: + patch
stage: test needed -> patch review
pull_requests: + pull_request8163
2018-06-19 08:40:22serhiy.storchakasetnosy: + pitrou
2018-06-18 22:40:29eryksuncreate