From feae50c9c5e6e0b18cea15d179a01fea5ea7a9e8 Mon Sep 17 00:00:00 2001 From: barneygale Date: Sat, 1 Jan 2022 05:18:10 +0000 Subject: [PATCH 1/3] bpo-44136: pathlib: merge `_Flavour.is_reserved()` into `PurePath.is_reserved()` Removes a bit more indirection. --- Lib/pathlib.py | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/Lib/pathlib.py b/Lib/pathlib.py index f1a33178e2958b..a628dd222a58a1 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -35,6 +35,12 @@ _WINERROR_INVALID_NAME, _WINERROR_CANT_RESOLVE_FILENAME) +_WIN_RESERVED_NAMES = ( + {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | + {'COM%s' % c for c in '123456789\xb9\xb2\xb3'} | + {'LPT%s' % c for c in '123456789\xb9\xb2\xb3'} +) + def _ignore_error(exception): return (getattr(exception, 'errno', None) in _IGNORED_ERRNOS or getattr(exception, 'winerror', None) in _IGNORED_WINERRORS) @@ -123,11 +129,6 @@ class _WindowsFlavour(_Flavour): drive_letters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') ext_namespace_prefix = '\\\\?\\' - reserved_names = ( - {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | - {'COM%s' % c for c in '123456789\xb9\xb2\xb3'} | - {'LPT%s' % c for c in '123456789\xb9\xb2\xb3'} - ) # Interesting findings about extended paths: # * '\\?\c:\a' is an extended path, which bypasses normal Windows API @@ -202,19 +203,6 @@ def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix): s = '\\' + s[3:] return prefix, s - def is_reserved(self, parts): - # NOTE: the rules for reserved names seem somewhat complicated - # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not - # exist). We err on the side of caution and return True for paths - # which are not considered reserved by Windows. - if not parts: - return False - if parts[0].startswith('\\\\'): - # UNC paths are never reserved - return False - name = parts[-1].partition('.')[0].partition(':')[0].rstrip(' ') - return name.upper() in self.reserved_names - def make_uri(self, path): # Under Windows, file URIs use the UTF-8 encoding. drive = path.drive @@ -260,9 +248,6 @@ def casefold_parts(self, parts): def compile_pattern(self, pattern): return re.compile(fnmatch.translate(pattern)).fullmatch - def is_reserved(self, parts): - return False - def make_uri(self, path): # We represent the path using the local filesystem encoding, # for portability to other applications. @@ -885,7 +870,7 @@ def is_absolute(self): def is_reserved(self): """Return True if the path contains one of the special names reserved by the system, if any.""" - return self._flavour.is_reserved(self._parts) + return False def match(self, path_pattern): """ @@ -936,6 +921,22 @@ class PureWindowsPath(PurePath): _flavour = _windows_flavour __slots__ = () + def is_reserved(self): + """Return True if the path contains one of the special names reserved + by the system, if any.""" + # NOTE: the rules for reserved names seem somewhat complicated + # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not + # exist). We err on the side of caution and return True for paths + # which are not considered reserved by Windows. + parts = self._parts + if not parts: + return False + if parts[0].startswith('\\\\'): + # UNC paths are never reserved + return False + name = parts[-1].partition('.')[0].partition(':')[0].rstrip(' ') + return name.upper() in _WIN_RESERVED_NAMES + # Filesystem-accessing classes From a2baccf336ad328c7732ebdb1c90de8259ffeb4b Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Sat, 1 Jan 2022 13:04:19 +0000 Subject: [PATCH 2/3] Update Lib/pathlib.py Co-authored-by: Oleg Iarygin --- Lib/pathlib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/pathlib.py b/Lib/pathlib.py index a628dd222a58a1..8e4a2678be4e8e 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -37,8 +37,8 @@ _WIN_RESERVED_NAMES = ( {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | - {'COM%s' % c for c in '123456789\xb9\xb2\xb3'} | - {'LPT%s' % c for c in '123456789\xb9\xb2\xb3'} + {f'COM{c}' for c in '123456789\xb9\xb2\xb3'} | + {f'LPT{c}' for c in '123456789\xb9\xb2\xb3'} ) def _ignore_error(exception): From 7fb9b0a099dad5bede555a8798b82a1a5ed535d0 Mon Sep 17 00:00:00 2001 From: barneygale Date: Sat, 5 Feb 2022 23:02:58 +0000 Subject: [PATCH 3/3] Delete duplicated docstring --- Lib/pathlib.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 8e4a2678be4e8e..28aa82ab942143 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -922,8 +922,6 @@ class PureWindowsPath(PurePath): __slots__ = () def is_reserved(self): - """Return True if the path contains one of the special names reserved - by the system, if any.""" # NOTE: the rules for reserved names seem somewhat complicated # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not # exist). We err on the side of caution and return True for paths