diff -r 4e33c343a264 Doc/library/pathlib.rst --- a/Doc/library/pathlib.rst Mon May 12 20:36:46 2014 +0200 +++ b/Doc/library/pathlib.rst Tue May 13 08:55:00 2014 +0300 @@ -917,3 +917,15 @@ Remove this file or symbolic link. If the path points to a directory, use :func:`Path.rmdir` instead. + +.. method:: Path.expanduser() + + Return a new :class:`Path` with expanded ``~`` and ``~user`` constructs, + as returned by :meth:`os.path.expanduser`. + + >>> p = PosixPath('~films') + >>> p.expanduser() + PosixPath('/home/ericidle/films') + + .. versionadded:: 3.5 + diff -r 4e33c343a264 Lib/pathlib.py --- a/Lib/pathlib.py Mon May 12 20:36:46 2014 +0200 +++ b/Lib/pathlib.py Tue May 13 08:55:00 2014 +0300 @@ -961,6 +961,12 @@ """ return cls(os.getcwd()) + def expanduser(self): + """ Return a new path with expanded ~ and ~user constructs + (as returned by os.path.expanduser) + """ + return self.__class__(os.path.expanduser(str(self))) + def iterdir(self): """Iterate over the files in this directory. Does not yield any result for the special paths '.' and '..'. diff -r 4e33c343a264 Lib/test/test_pathlib.py --- a/Lib/test/test_pathlib.py Mon May 12 20:36:46 2014 +0200 +++ b/Lib/test/test_pathlib.py Tue May 13 08:55:00 2014 +0300 @@ -1256,6 +1256,60 @@ p = self.cls('') self.assertEqual(p.stat(), os.stat('.')) + def test_expanduser(self): + p = self.cls('~') + self.assertEqual(os.path.expanduser(str(p)), + str(p.expanduser())) + + @unittest.skipUnless(os.name == 'posix', + "test meaningful only on posix systems") + def test_expanduser_posix(self): + try: + import pwd + except ImportError: + pass + else: + with support.EnvironmentVarGuard() as env: + env['HOME'] = '/' + p1 = self.cls('~') + p2 = self.cls('~/foo') + self.assertEqual(str(p1.expanduser()), "/") + self.assertEqual(str(p2.expanduser()), "/foo") + # expanduser should fall back to using the password database + del env['HOME'] + home = pwd.getpwuid(os.getuid()).pw_dir + # $HOME can end with a trailing /, so strip it (see #17809) + self.assertEqual(str(self.cls("~").expanduser()), + home.rstrip("/")) + + @unittest.skipUnless(os.name == 'nt', + "test meaningful only on Windows") + def test_expanduser_nt(self): + with support.EnvironmentVarGuard() as env: + env.pop('HOME', None) + env.pop('USERPROFILE', None) + env.pop('HOMEPATH', None) + + # test that the path returns unchanged + p1 = self.cls('~') + self.assertEqual(str(p1.expanduser()), '~') + + # test the first lookup key in the env vars + env['HOME'] = 'C:\\test' + p2 = self.cls('~') + self.assertEqual(str(p2.expanduser()), 'C:\\test') + + # test that HOMEPATH is available instead + env.pop('HOME', None) + env['HOMEPATH'] = 'C:\\idle' + p3 = self.cls('~') + self.assertEqual(str(p3.expanduser()), 'C:\\idle') + + env['HOMEDRIVE'] = 'C:\\' + env['HOMEPATH'] = 'eggs' + p4 = self.cls('~') + self.assertEqual(str(p4.expanduser()), 'C:\\eggs') + def test_exists(self): P = self.cls p = P(BASE)