Skip to content

Commit

Permalink
pythonGH-123599: Deprecate duplicate pathname2url() implementation
Browse files Browse the repository at this point in the history
Call `urllib.request.pathname2url()` from `pathlib.Path.as_uri()`, and
deprecate the duplicate implementation in `PurePath`.
  • Loading branch information
barneygale committed Nov 29, 2024
1 parent b83be9c commit e17fc75
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 20 deletions.
8 changes: 5 additions & 3 deletions Doc/library/pathlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -886,9 +886,11 @@ conforming to :rfc:`8089`.
>>> p.as_uri()
'file:///c:/Windows'
For historical reasons, this method is also available from
:class:`PurePath` objects. However, its use of :func:`os.fsencode` makes
it strictly impure.
.. deprecated-removed:: 3.14 3.16

Calling this method from :class:`PurePath` rather than :class:`Path` is
possible but deprecated. The method's use of :func:`os.fsencode` makes
it strictly impure.


Expanding and resolving paths
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,11 @@ Deprecated
write new code. The :mod:`subprocess` module is recommended instead.
(Contributed by Victor Stinner in :gh:`120743`.)

* :mod:`pathlib`:
:meth:`!pathlib.PurePath.as_uri` is deprecated and will be removed in Python
3.16. Use :meth:`pathlib.Path.as_uri` instead.
(Contributed by Barney Gale in :gh:`123599`.)

* :mod:`symtable`:
Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest.
(Contributed by Bénédikt Tran in :gh:`119698`.)
Expand Down
13 changes: 11 additions & 2 deletions Lib/pathlib/_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import posixpath
import sys
import warnings
from glob import _StringGlobber
from itertools import chain
from _collections_abc import Sequence
Expand Down Expand Up @@ -451,7 +452,6 @@ 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."""
import warnings
msg = ("pathlib.PurePath.is_reserved() is deprecated and scheduled "
"for removal in Python 3.15. Use os.path.isreserved() to "
"detect reserved paths on Windows.")
Expand All @@ -462,6 +462,9 @@ def is_reserved(self):

def as_uri(self):
"""Return the path as a URI."""
msg = ("pathlib.PurePath.as_uri() is deprecated and scheduled "
"for removal in Python 3.16. Use pathlib.Path.as_uri().")
warnings.warn(msg, DeprecationWarning, stacklevel=2)
if not self.is_absolute():
raise ValueError("relative path can't be expressed as a file URI")

Expand Down Expand Up @@ -524,7 +527,6 @@ class Path(PathBase, PurePath):
but cannot instantiate a WindowsPath on a POSIX system or vice versa.
"""
__slots__ = ()
as_uri = PurePath.as_uri

@classmethod
def _unsupported_msg(cls, attribute):
Expand Down Expand Up @@ -900,6 +902,13 @@ def expanduser(self):

return self

def as_uri(self):
"""Return the path as a URI."""
if not self.is_absolute():
raise ValueError("relative path can't be expressed as a file URI")
from urllib.request import pathname2url
return 'file:' + pathname2url(str(self))

@classmethod
def from_uri(cls, uri):
"""Return a new path from the given 'file' URI."""
Expand Down
36 changes: 21 additions & 15 deletions Lib/test/test_pathlib/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,18 @@ def assertLess(a, b):
with self.assertRaises(TypeError):
P() < {}

def make_uri(self, path):
if isinstance(path, pathlib.Path):
return path.as_uri()
with self.assertWarns(DeprecationWarning):
return path.as_uri()

def test_as_uri_common(self):
P = self.cls
with self.assertRaises(ValueError):
P('a').as_uri()
self.make_uri(P('a'))
with self.assertRaises(ValueError):
P().as_uri()
self.make_uri(P())

def test_repr_roundtrips(self):
for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
Expand Down Expand Up @@ -369,9 +375,9 @@ def test_eq_posix(self):
@needs_posix
def test_as_uri_posix(self):
P = self.cls
self.assertEqual(P('/').as_uri(), 'file:///')
self.assertEqual(P('/a/b.c').as_uri(), 'file:///a/b.c')
self.assertEqual(P('/a/b%#c').as_uri(), 'file:///a/b%25%23c')
self.assertEqual(self.make_uri(P('/')), 'file:///')
self.assertEqual(self.make_uri(P('/a/b.c')), 'file:///a/b.c')
self.assertEqual(self.make_uri(P('/a/b%#c')), 'file:///a/b%25%23c')

@needs_posix
def test_as_uri_non_ascii(self):
Expand All @@ -381,7 +387,7 @@ def test_as_uri_non_ascii(self):
os.fsencode('\xe9')
except UnicodeEncodeError:
self.skipTest("\\xe9 cannot be encoded to the filesystem encoding")
self.assertEqual(P('/a/b\xe9').as_uri(),
self.assertEqual(self.make_uri(P('/a/b\xe9')),
'file:///a/b' + quote_from_bytes(os.fsencode('\xe9')))

@needs_posix
Expand Down Expand Up @@ -475,17 +481,17 @@ def test_eq_windows(self):
def test_as_uri_windows(self):
P = self.cls
with self.assertRaises(ValueError):
P('/a/b').as_uri()
self.make_uri(P('/a/b'))
with self.assertRaises(ValueError):
P('c:a/b').as_uri()
self.assertEqual(P('c:/').as_uri(), 'file:///c:/')
self.assertEqual(P('c:/a/b.c').as_uri(), 'file:///c:/a/b.c')
self.assertEqual(P('c:/a/b%#c').as_uri(), 'file:///c:/a/b%25%23c')
self.assertEqual(P('c:/a/b\xe9').as_uri(), 'file:///c:/a/b%C3%A9')
self.assertEqual(P('//some/share/').as_uri(), 'file://some/share/')
self.assertEqual(P('//some/share/a/b.c').as_uri(),
self.make_uri(P('c:a/b'))
self.assertEqual(self.make_uri(P('c:/')), 'file:///c:/')
self.assertEqual(self.make_uri(P('c:/a/b.c')), 'file:///c:/a/b.c')
self.assertEqual(self.make_uri(P('c:/a/b%#c')), 'file:///c:/a/b%25%23c')
self.assertEqual(self.make_uri(P('c:/a/b\xe9')), 'file:///c:/a/b%C3%A9')
self.assertEqual(self.make_uri(P('//some/share/')), 'file://some/share/')
self.assertEqual(self.make_uri(P('//some/share/a/b.c')),
'file://some/share/a/b.c')
self.assertEqual(P('//some/share/a/b%#c\xe9').as_uri(),
self.assertEqual(self.make_uri(P('//some/share/a/b%#c\xe9')),
'file://some/share/a/b%25%23c%C3%A9')

@needs_windows
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Deprecate :meth:`!pathlib.PurePath.as_uri`; use :meth:`pathlib.Path.as_uri`
instead.

0 comments on commit e17fc75

Please sign in to comment.