Skip to content

Commit 06b0c74

Browse files
committed
bpo-29688: document and test pathlib.Path.absolute().
1 parent 0b58bac commit 06b0c74

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

Doc/library/pathlib.rst

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,20 @@ call fails (for example because the path doesn't exist).
10521052
Added return value, return the new Path instance.
10531053

10541054

1055+
.. method:: Path.absolute()
1056+
1057+
Make the path absolute, without resolving symlinks, and return a new path
1058+
object. This is equivalent to prepending the current directory::
1059+
1060+
>>> p = Path('..')
1061+
>>> p
1062+
PosixPath('..')
1063+
>>> p.absolute()
1064+
PosixPath('/home/antoine/pathlib/..')
1065+
>>> Path.cwd() / p
1066+
PosixPath('/home/antoine/pathlib/..')
1067+
1068+
10551069
.. method:: Path.resolve(strict=False)
10561070

10571071
Make the path absolute, resolving any symlinks. A new path object is
@@ -1239,13 +1253,14 @@ Below is a table mapping various :mod:`os` functions to their corresponding
12391253

12401254
Not all pairs of functions/methods below are equivalent. Some of them,
12411255
despite having some overlapping use-cases, have different semantics. They
1242-
include :func:`os.path.abspath` and :meth:`Path.resolve`,
1256+
include :func:`os.path.abspath` and :meth:`Path.absolute`,
12431257
:func:`os.path.relpath` and :meth:`PurePath.relative_to`.
12441258

12451259
==================================== ==============================
12461260
:mod:`os` and :mod:`os.path` :mod:`pathlib`
12471261
==================================== ==============================
1248-
:func:`os.path.abspath` :meth:`Path.resolve` [#]_
1262+
:func:`os.path.abspath` :meth:`Path.absolute` [#]_
1263+
:func:`os.path.realpath` :meth:`Path.resolve`
12491264
:func:`os.chmod` :meth:`Path.chmod`
12501265
:func:`os.mkdir` :meth:`Path.mkdir`
12511266
:func:`os.makedirs` :meth:`Path.mkdir`
@@ -1278,5 +1293,5 @@ Below is a table mapping various :mod:`os` functions to their corresponding
12781293

12791294
.. rubric:: Footnotes
12801295

1281-
.. [#] :func:`os.path.abspath` does not resolve symbolic links while :meth:`Path.resolve` does.
1296+
.. [#] :func:`os.path.abspath` normalizes the resulting path, which may change its meaning in the presence of symlinks.
12821297
.. [#] :meth:`Path.relative_to` requires ``self`` to be the subpath of the argument, but :func:`os.path.relpath` does not.

Lib/pathlib.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,24 +1046,19 @@ def rglob(self, pattern):
10461046
yield p
10471047

10481048
def absolute(self):
1049-
"""Return an absolute version of this path. This function works
1050-
even if the path doesn't point to anything.
1049+
"""Return an absolute version of this path by prepending the current
1050+
working directory. No normalization or symlink resolution is performed.
10511051
1052-
No normalization is done, i.e. all '.' and '..' will be kept along.
10531052
Use resolve() to get the canonical path to a file.
10541053
"""
1055-
# XXX untested yet!
10561054
if self.is_absolute():
10571055
return self
1058-
# FIXME this must defer to the specific flavour (and, under Windows,
1059-
# use nt._getfullpathname())
10601056
return self._from_parts([self._accessor.getcwd()] + self._parts)
10611057

10621058
def resolve(self, strict=False):
10631059
"""
10641060
Make the path absolute, resolving all symlinks on the way and also
1065-
normalizing it (for example turning slashes into backslashes under
1066-
Windows).
1061+
normalizing it.
10671062
"""
10681063

10691064
def check_eloop(e):

Lib/test/test_pathlib.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,39 @@ def test_cwd(self):
14561456
p = self.cls.cwd()
14571457
self._test_cwd(p)
14581458

1459+
def _test_absolute(self):
1460+
P = self.cls
1461+
1462+
# Simple absolute paths
1463+
self.assertEqualNormCase(str(P('/').absolute()), '/')
1464+
self.assertEqualNormCase(str(P('/a').absolute()), '/a')
1465+
self.assertEqualNormCase(str(P('/a/b').absolute()), '/a/b')
1466+
self.assertEqualNormCase(str(P('//a/b').absolute()), '//a/b')
1467+
1468+
# Simple relative paths
1469+
self.assertEqualNormCase(str(P().absolute()), BASE)
1470+
self.assertEqualNormCase(str(P('.').absolute()), BASE)
1471+
self.assertEqualNormCase(str(P('a').absolute()), os.path.join(BASE, 'a'))
1472+
self.assertEqualNormCase(str(P('a', 'b', 'c').absolute()), os.path.join(BASE, 'a', 'b', 'c'))
1473+
1474+
# Symlinks should not be resolved
1475+
self.assertEqualNormCase(str(P('linkB', 'fileB').absolute()), os.path.join(BASE, 'linkB', 'fileB'))
1476+
self.assertEqualNormCase(str(P('brokenLink').absolute()), os.path.join(BASE, 'brokenLink'))
1477+
self.assertEqualNormCase(str(P('brokenLinkLoop').absolute()), os.path.join(BASE, 'brokenLinkLoop'))
1478+
1479+
# '..' entries should be preserved and not normalised
1480+
self.assertEqualNormCase(str(P('..').absolute()), os.path.join(BASE, '..'))
1481+
self.assertEqualNormCase(str(P('a', '..').absolute()), os.path.join(BASE, 'a', '..'))
1482+
self.assertEqualNormCase(str(P('..', 'b').absolute()), os.path.join(BASE, '..', 'b'))
1483+
1484+
def test_absolute(self):
1485+
old_path = os.getcwd()
1486+
os.chdir(BASE)
1487+
try:
1488+
self._test_absolute()
1489+
finally:
1490+
os.chdir(old_path)
1491+
14591492
def _test_home(self, p):
14601493
q = self.cls(os.path.expanduser('~'))
14611494
self.assertEqual(p, q)

0 commit comments

Comments
 (0)