Skip to content

Commit

Permalink
bpo-46556: emit DeprecationWarning from pathlib.Path.__enter__() (G…
Browse files Browse the repository at this point in the history
…H-30971)

In Python 3.9, Path.__exit__() was made a no-op and has never been documented.

Co-authored-by: Brett Cannon <brett@python.org>
  • Loading branch information
barneygale and brettcannon authored Feb 8, 2022
1 parent 81c7204 commit 06e1701
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 12 deletions.
19 changes: 11 additions & 8 deletions Lib/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,17 +877,20 @@ def _make_child_relpath(self, part):
return self._from_parsed_parts(self._drv, self._root, parts)

def __enter__(self):
# In previous versions of pathlib, __exit__() 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 __exit__() was made a no-op.
# In Python 3.11 __enter__() began emitting DeprecationWarning.
# In Python 3.13 __enter__() and __exit__() should be removed.
warnings.warn("pathlib.Path.__enter__() is deprecated and scheduled "
"for removal in Python 3.13; Path objects as a context "
"manager is a no-op",
DeprecationWarning, stacklevel=2)
return self

def __exit__(self, t, v, tb):
# 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

# Public API
Expand Down
11 changes: 7 additions & 4 deletions Lib/test/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1850,17 +1850,20 @@ def test_with(self):
it = p.iterdir()
it2 = p.iterdir()
next(it2)
with p:
pass
# bpo-46556: path context managers are deprecated in Python 3.11.
with self.assertWarns(DeprecationWarning):
with p:
pass
# 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
with self.assertWarns(DeprecationWarning):
with p:
pass

def test_chmod(self):
p = self.cls(BASE) / 'fileA'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Deprecate undocumented support for using a :class:`pathlib.Path` object as a
context manager.

0 comments on commit 06e1701

Please # to comment.