GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — bpo-39682: make `pathlib.Path` immutable by removing (undocumented) support for "closing" a path by using it as a context manager by barneygale · Pull Request #18846 · python/cpython

bpo-39682: make pathlib.Path immutable by removing (undocumented) support for "closing" a path by using it as a context manager #18846

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Sign up for GitHub

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
pitrou merged 2 commits into python:master from barneygale:bpo-39682-pathlib-path-context-manager
Apr 1, 2020

Uh oh!

There was an error while loading. Please reload this page.

Merged

bpo-39682: make pathlib.Path immutable by removing (undocumented) support for "closing" a path by using it as a context manager #18846

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
2 commits
Select commit Hold shift + click to select a range
31c116a
bpo-39682: make `pathlib.Path` immutable by removing (undocumented) s…
barneygale Mar 8, 2020
d9aa9df
Update Misc/NEWS.d/next/Library/2020-03-08-11-00-01.bpo-39682.AxXZNz.rst
barneygale Mar 30, 2020
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

51 changes: 9 additions & 42 deletions 51 Lib/pathlib.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,6 @@ class Path(PurePath):
"""
__slots__ = (
'_accessor',
'_closed',
)

def __new__(cls, *args, **kwargs):
Expand All @@ -1058,7 +1057,6 @@ def _init(self,
# Private non-constructor arguments
template=None,
):
self._closed = False
if template is not None:
self._accessor = template._accessor
else:
Expand All @@ -1071,15 +1069,18 @@ def _make_child_relpath(self, part):
return self._from_parsed_parts(self._drv, self._root, parts)

def __enter__(self):
Comment thread
barneygale marked this conversation as resolved.
Resolved

Uh oh!

There was an error while loading. Please reload this page.

if self._closed:
self._raise_closed()
return self

def __exit__(self, t, v, tb):
self._closed = True

def _raise_closed(self):
raise ValueError("I/O operation on closed path")
# https://bugs.python.org/issue39682
# In previous versions of pathlib, this method marked this path as
# closed; subsequent attempts to perform I/O would raise an IOError.
# This functionality was never documented, and had the effect of
# making Path objects mutable, contrary to PEP 428. In Python 3.9 the
# _closed attribute was removed, and this method made a no-op.
# This method and __enter__()/__exit__() should be deprecated and
# removed in the future.
pass
Comment thread
barneygale marked this conversation as resolved.
Resolved

Uh oh!

There was an error while loading. Please reload this page.


def _opener(self, name, flags, mode=0o666):
# A stub for the opener argument to built-in open()
Expand All @@ -1090,8 +1091,6 @@ def _raw_open(self, flags, mode=0o777):
Open the file pointed by this path and return a file descriptor,
as os.open() does.
"""
if self._closed:
self._raise_closed()
return self._accessor.open(self, flags, mode)

# Public API
Expand Down Expand Up @@ -1125,15 +1124,11 @@ def iterdir(self):
"""Iterate over the files in this directory. Does not yield any
result for the special paths '.' and '..'.
"""
if self._closed:
self._raise_closed()
for name in self._accessor.listdir(self):
if name in {'.', '..'}:
# Yielding a path object for these makes little sense
continue
yield self._make_child_relpath(name)
if self._closed:
self._raise_closed()

def glob(self, pattern):
"""Iterate over this subtree and yield all existing files (of any
Expand Down Expand Up @@ -1170,8 +1165,6 @@ def absolute(self):
Use resolve() to get the canonical path to a file.
"""
# XXX untested yet!
if self._closed:
self._raise_closed()
if self.is_absolute():
return self
# FIXME this must defer to the specific flavour (and, under Windows,
Expand All @@ -1186,8 +1179,6 @@ def resolve(self, strict=False):
normalizing it (for example turning slashes into backslashes under
Windows).
"""
if self._closed:
self._raise_closed()
s = self._flavour.resolve(self, strict=strict)
if s is None:
# No symlink resolution => for consistency, raise an error if
Expand Down Expand Up @@ -1227,8 +1218,6 @@ def open(self, mode='r', buffering=-1, encoding=None,
Open the file pointed by this path and return a file object, as
the built-in open() function does.
"""
if self._closed:
self._raise_closed()
return io.open(self, mode, buffering, encoding, errors, newline,
opener=self._opener)

Expand Down Expand Up @@ -1278,8 +1267,6 @@ def touch(self, mode=0o666, exist_ok=True):
"""
Create this file with the given access mode, if it doesn't exist.
"""
if self._closed:
self._raise_closed()
if exist_ok:
# First try to bump modification time
# Implementation note: GNU touch uses the UTIME_NOW option of
Expand All @@ -1301,8 +1288,6 @@ def mkdir(self, mode=0o777, parents=False, exist_ok=False):
"""
Create a new directory at this given path.
"""
if self._closed:
self._raise_closed()
try:
self._accessor.mkdir(self, mode)
except FileNotFoundError:
Expand All @@ -1320,26 +1305,20 @@ def chmod(self, mode):
"""
Change the permissions of the path, like os.chmod().
"""
if self._closed:
self._raise_closed()
self._accessor.chmod(self, mode)

def lchmod(self, mode):
"""
Like chmod(), except if the path points to a symlink, the symlink's
permissions are changed, rather than its target's.
"""
if self._closed:
self._raise_closed()
self._accessor.lchmod(self, mode)

def unlink(self, missing_ok=False):
"""
Remove this file or link.
If the path is a directory, use rmdir() instead.
"""
if self._closed:
self._raise_closed()
try:
self._accessor.unlink(self)
except FileNotFoundError:
Expand All @@ -1350,34 +1329,26 @@ def rmdir(self):
"""
Remove this directory. The directory must be empty.
"""
if self._closed:
self._raise_closed()
self._accessor.rmdir(self)

def lstat(self):
"""
Like stat(), except if the path points to a symlink, the symlink's
status information is returned, rather than its target's.
"""
if self._closed:
self._raise_closed()
return self._accessor.lstat(self)

def link_to(self, target):
"""
Create a hard link pointing to a path named target.
"""
if self._closed:
self._raise_closed()
self._accessor.link_to(self, target)

def rename(self, target):
"""
Rename this path to the given path,
and return a new Path instance pointing to the given path.
"""
if self._closed:
self._raise_closed()
self._accessor.rename(self, target)
return self.__class__(target)

Expand All @@ -1387,8 +1358,6 @@ def replace(self, target):
destination if it exists, and return a new Path instance
pointing to the given path.
"""
if self._closed:
self._raise_closed()
self._accessor.replace(self, target)
return self.__class__(target)

Expand All @@ -1397,8 +1366,6 @@ def symlink_to(self, target, target_is_directory=False):
Make this path a symlink pointing to the given path.
Note the order of arguments (self, target) is the reverse of os.symlink's.
"""
if self._closed:
self._raise_closed()
self._accessor.symlink(target, self, target_is_directory)

# Convenience functions for querying the stat results
Expand Down
16 changes: 9 additions & 7 deletions 16 Lib/test/test_pathlib.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -1720,13 +1720,15 @@ def test_with(self):
next(it2)
with p:
pass
# I/O operation on closed path.
self.assertRaises(ValueError, next, it)
self.assertRaises(ValueError, next, it2)
self.assertRaises(ValueError, p.open)
self.assertRaises(ValueError, p.resolve)
self.assertRaises(ValueError, p.absolute)
self.assertRaises(ValueError, p.__enter__)
# Using a path as a context manager is a no-op, thus the following
# operations should still succeed after the context manage exits.
next(it)
next(it2)
p.exists()
p.resolve()
p.absolute()
with p:
pass

def test_chmod(self):
p = self.cls(BASE) / 'fileA'
Expand Down
3 changes: 3 additions & 0 deletions 3 Misc/NEWS.d/next/Library/2020-03-08-11-00-01.bpo-39682.AxXZNz.rst
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Remove undocumented support for *closing* a `pathlib.Path` object via its
context manager. The context manager magic methods remain, but they are now a
no-op, making `Path` objects immutable.
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.