summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/pathlib.rst23
-rw-r--r--Lib/pathlib.py22
-rw-r--r--Lib/test/test_pathlib.py11
-rw-r--r--Misc/NEWS14
4 files changed, 56 insertions, 14 deletions
diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst
index ff5196d..ca44a65 100644
--- a/Doc/library/pathlib.rst
+++ b/Doc/library/pathlib.rst
@@ -31,12 +31,6 @@ Pure paths are useful in some special cases; for example:
accessing the OS. In this case, instantiating one of the pure classes may be
useful since those simply don't have any OS-accessing operations.
-.. note::
- This module has been included in the standard library on a
- :term:`provisional basis <provisional package>`. Backwards incompatible
- changes (up to and including removal of the package) may occur if deemed
- necessary by the core developers.
-
.. seealso::
:pep:`428`: The pathlib module -- object-oriented filesystem paths.
@@ -107,7 +101,8 @@ we also call *flavours*:
PurePosixPath('setup.py')
Each element of *pathsegments* can be either a string representing a
- path segment, or another path object::
+ path segment, an object implementing the :class:`os.PathLike` interface
+ which returns a string, or another path object::
>>> PurePath('foo', 'some/path', 'bar')
PurePosixPath('foo/some/path/bar')
@@ -148,6 +143,12 @@ we also call *flavours*:
to ``PurePosixPath('bar')``, which is wrong if ``foo`` is a symbolic link
to another directory)
+ Pure path objects implement the :class:`os.PathLike` interface, allowing them
+ to be used anywhere the interface is accepted.
+
+ .. versionchanged:: 3.6
+ Added support for the :class:`os.PathLike` interface.
+
.. class:: PurePosixPath(*pathsegments)
A subclass of :class:`PurePath`, this path flavour represents non-Windows
@@ -212,6 +213,14 @@ The slash operator helps create child paths, similarly to :func:`os.path.join`::
>>> '/usr' / q
PurePosixPath('/usr/bin')
+A path object can be used anywhere an object implementing :class:`os.PathLike`
+is accepted::
+
+ >>> import os
+ >>> p = PurePath('/etc')
+ >>> os.fspath(p)
+ '/etc'
+
The string representation of a path is the raw filesystem path itself
(in native form, e.g. with backslashes under Windows), which you can
pass to any function taking a file path as a string::
diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index 1480e2f..a06676f 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -634,13 +634,16 @@ class PurePath(object):
for a in args:
if isinstance(a, PurePath):
parts += a._parts
- elif isinstance(a, str):
- # Force-cast str subclasses to str (issue #21127)
- parts.append(str(a))
else:
- raise TypeError(
- "argument should be a path or str object, not %r"
- % type(a))
+ a = os.fspath(a)
+ if isinstance(a, str):
+ # Force-cast str subclasses to str (issue #21127)
+ parts.append(str(a))
+ else:
+ raise TypeError(
+ "argument should be a str object or an os.PathLike "
+ "object returning str, not %r"
+ % type(a))
return cls._flavour.parse_parts(parts)
@classmethod
@@ -693,6 +696,9 @@ class PurePath(object):
self._parts) or '.'
return self._str
+ def __fspath__(self):
+ return str(self)
+
def as_posix(self):
"""Return the string representation of the path with forward (/)
slashes."""
@@ -943,6 +949,10 @@ class PurePath(object):
return False
return True
+# Can't subclass os.PathLike from PurePath and keep the constructor
+# optimizations in PurePath._parse_args().
+os.PathLike.register(PurePath)
+
class PurePosixPath(PurePath):
_flavour = _posix_flavour
diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index fbbd448..2f2ba3c 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -190,13 +190,18 @@ class _BasePurePathTest(object):
P = self.cls
p = P('a')
self.assertIsInstance(p, P)
+ class PathLike:
+ def __fspath__(self):
+ return "a/b/c"
P('a', 'b', 'c')
P('/a', 'b', 'c')
P('a/b/c')
P('/a/b/c')
+ P(PathLike())
self.assertEqual(P(P('a')), P('a'))
self.assertEqual(P(P('a'), 'b'), P('a/b'))
self.assertEqual(P(P('a'), P('b')), P('a/b'))
+ self.assertEqual(P(P('a'), P('b'), P('c')), P(PathLike()))
def _check_str_subclass(self, *args):
# Issue #21127: it should be possible to construct a PurePath object
@@ -384,6 +389,12 @@ class _BasePurePathTest(object):
parts = p.parts
self.assertEqual(parts, (sep, 'a', 'b'))
+ def test_fspath_common(self):
+ P = self.cls
+ p = P('a/b')
+ self._check_str(p.__fspath__(), ('a/b',))
+ self._check_str(os.fspath(p), ('a/b',))
+
def test_equivalences(self):
for k, tuples in self.equivalences.items():
canon = k.replace('/', self.sep)
diff --git a/Misc/NEWS b/Misc/NEWS
index f382b3f..8eaed23 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.6.0 alpha 2
Core and Builtins
-----------------
+- Issue #27186: Add support for os.PathLike objects to open() (part of PEP 519).
+
- Issue #27066: Fixed SystemError if a custom opener (for open()) returns a
negative number without setting an exception.
@@ -36,6 +38,14 @@ Core and Builtins
Library
-------
+- Issue #27186: Add os.PathLike support to pathlib, removing its provisional
+ status (part of PEP 519).
+
+- Issue #27186: Add support for os.PathLike objects to os.fsencode() and
+ os.fsdecode() (part of PEP 519).
+
+- Issue #27186: Introduce os.PathLike and os.fspath() (part of PEP 519).
+
- A new version of typing.py provides several new classes and
features: @overload outside stubs, Reversible, DefaultDict, Text,
ContextManager, Type[], NewType(), TYPE_CHECKING, and numerous bug
@@ -198,12 +208,14 @@ Build
Misc
----
-- Issue #17500, and https://github.com/python/pythondotorg/issues/945: Remove
+- Issue #17500, and https://github.com/python/pythondotorg/issues/945: Remove
unused and outdated icons.
C API
-----
+- Issue #27186: Add the PyOS_FSPath() function (part of PEP 519).
+
- Issue #26282: PyArg_ParseTupleAndKeywords() now supports positional-only
parameters.