Skip to content

Commit

Permalink
Added support for dir fd argumentent to fake os.scandir()
Browse files Browse the repository at this point in the history
- introduced in Python 3.7, Posix only
- fixes #346
  • Loading branch information
mrbean-bremen committed Jan 26, 2018
1 parent 82176dc commit b3a4a78
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This version of pyfakefs does not support Python 2.6. Python 2.6 users
must use pyfakefs 3.3 or earlier.

#### New Features
* Added support for file descriptor path parameter in `os.scandir` (Python >= 3.7, Posix only) (see [#346](../../issues/346))
* Added support to fake out backported `scandir` module ([#332](../../issues/332))
* Dynamic loading of modules after setup is now on by default and no more considered experimental (see [#340](../../issues/340))
* `IOError`/`OSError` exception messages in the fake file system now always start with the message issued in the real file system in Unix systems (see [#202](../../issues/202))
Expand Down
8 changes: 8 additions & 0 deletions pyfakefs/fake_scandir.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"""
import sys

import os


class DirEntry(object):
"""Emulates os.DirEntry. Note that we did not enforce keyword only arguments."""
Expand Down Expand Up @@ -101,6 +103,12 @@ class ScanDirIter:

def __init__(self, filesystem, path):
self.filesystem = filesystem
if isinstance(path, int):
if sys.version_info < (3, 7) or self.filesystem.is_windows_fs:
raise NotImplementedError('scandir does not support file descriptor'
'path argument')
path = self.filesystem.get_open_file(path).get_object().path

self.path = self.filesystem.ResolvePath(path)
contents = {}
try:
Expand Down
40 changes: 32 additions & 8 deletions tests/fake_os_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4011,7 +4011,6 @@ def test_file_size_truncation(self):
class FakeScandirTest(FakeOsModuleTestBase):
def setUp(self):
super(FakeScandirTest, self).setUp()

self.supports_symlinks = (not self.is_windows or
not self.use_real_fs() and not self.is_python2)

Expand All @@ -4023,24 +4022,25 @@ def setUp(self):
scandir = lambda p: pyfakefs.fake_scandir.scandir(self.filesystem, p)
else:
scandir = self.os.scandir
self.scandir = scandir

directory = self.make_path('xyzzy', 'plugh')
self.directory = self.make_path('xyzzy', 'plugh')
link_dir = self.make_path('linked', 'plugh')
self.linked_file_path = self.os.path.join(link_dir, 'file')
self.linked_dir_path = self.os.path.join(link_dir, 'dir')

self.create_dir(self.linked_dir_path)
self.create_file(self.linked_file_path, contents=b'a' * 10)
self.dir_path = self.os.path.join(directory, 'dir')
self.dir_path = self.os.path.join(self.directory, 'dir')
self.create_dir(self.dir_path)
self.file_path = self.os.path.join(directory, 'file')
self.file_path = self.os.path.join(self.directory, 'file')
self.create_file(self.file_path, contents=b'b' * 50)
self.file_link_path = self.os.path.join(directory, 'link_file')
self.file_link_path = self.os.path.join(self.directory, 'link_file')
if self.supports_symlinks:
self.create_symlink(self.file_link_path, self.linked_file_path)
self.dir_link_path = self.os.path.join(directory, 'link_dir')
self.dir_link_path = self.os.path.join(self.directory, 'link_dir')
self.create_symlink(self.dir_link_path, self.linked_dir_path)
self.dir_entries = [entry for entry in scandir(directory)]
self.dir_entries = [entry for entry in self.scandir(self.directory)]
self.dir_entries = sorted(self.dir_entries,
key=lambda entry: entry.name)

Expand All @@ -4052,6 +4052,10 @@ def test_paths(self):
self.assertEqual(len(sorted_names), len(self.dir_entries))
self.assertEqual(sorted_names,
[entry.name for entry in self.dir_entries])

self.skip_real_fs()
# this one does not work in the real fs - will wait for
# final 3.7 release to check into this
self.assertEqual(self.dir_path, self.dir_entries[0].path)

def test_isfile(self):
Expand Down Expand Up @@ -4131,4 +4135,24 @@ def test_stat_ino_dev(self):

class RealScandirTest(FakeScandirTest):
def use_real_fs(self):
return True
return True


@unittest.skipIf(sys.version_info < (3, 7) or TestCase.is_windows,
'dir_fd support for os.scandir was introduced in Python 3.7')
class FakeScandirFdTest(FakeScandirTest):
def setUp(self):
super(FakeScandirFdTest, self).setUp()
self.dir_fd = self.os.open(self.directory, os.O_RDONLY)
self.dir_entries = [entry for entry in self.scandir(self.dir_fd)]
self.dir_entries = sorted(self.dir_entries,
key=lambda entry: entry.name)

def tearDown(self):
self.os.close(self.dir_fd)
super(FakeScandirFdTest, self).tearDown()


class RealScandirFdTest(FakeScandirFdTest):
def use_real_fs(self):
return True

0 comments on commit b3a4a78

Please sign in to comment.