diff --git a/Lib/pathlib.py b/Lib/pathlib.py --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -975,6 +975,24 @@ class Path(PurePath): if self._closed: self._raise_closed() + def files(self, include_symlinks=True): + """Iterate over the regular files in this directory. + """ + if include_symlinks: + return (f for f in self.iterdir() if f.is_file()) + else: + return (f for f in self.iterdir() + if f.is_file() and not f.is_symlink()) + + def subdirs(self, include_symlinks=True): + """Iterate over the subdirectories in this directory. + """ + if include_symlinks: + return (f for f in self.iterdir() if f.is_dir()) + else: + return (f for f in self.iterdir() + if f.is_dir() and not f.is_symlink()) + def glob(self, pattern): """Iterate over this subtree and yield all existing files (of any kind, including directories) matching the given pattern. diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1309,6 +1309,26 @@ class _BasePathTest(object): self.assertIn(cm.exception.errno, (errno.ENOTDIR, errno.ENOENT, errno.EINVAL)) + def test_files(self): + P = self.cls + p = P(BASE) + paths = set(p.files()) + files = {'fileA'} + links = {'linkA'} if not symlink_skip_reason else set() + self.assertEqual(paths, { P(BASE, q) for q in files | links }) + paths = set(p.files(include_symlinks=False)) + self.assertEqual(paths, { P(BASE, q) for q in files }) + + def test_subdirs(self): + P = self.cls + p = P(BASE) + paths = set(p.subdirs()) + subdirs = {'dirA', 'dirB', 'dirC'} + links = {'linkB'} if not symlink_skip_reason else set() + self.assertEqual(paths, { P(BASE, q) for q in subdirs | links }) + paths = set(p.subdirs(include_symlinks=False)) + self.assertEqual(paths, { P(BASE, q) for q in subdirs }) + def test_glob_common(self): def _check(glob, expected): self.assertEqual(set(glob), { P(BASE, q) for q in expected })