Permalink
Browse files

Add support for pathlib2 (#408) (#422)

Well done.
  • Loading branch information...
matthew16550 authored and jmcgeheeiv committed Sep 3, 2018
1 parent 8990455 commit 05e7d2a1616239c334d61ac7087e46e4506cf24f
View
@@ -45,4 +45,5 @@ if [[ $TRAVIS_OS_NAME == 'osx' ]]; then
fi
pip install -r requirements.txt
pip install -r extra_requirements.txt
pip install .
View
@@ -18,3 +18,4 @@ flake8 . $EXCLUDES --count --select=E901,E999,F821,F822,F823 --show-source --sta
# exit-zero treats all errors as warnings
flake8 . $EXCLUDES --count --exit-zero --max-complexity=12 --statistics
python -m pyfakefs.tests.all_tests
python -m pyfakefs.tests.all_tests_without_extra_packages
View
@@ -8,12 +8,14 @@ environment:
install:
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
- "%PYTHON%\\python.exe -m pip install -r extra_requirements.txt"
- "%PYTHON%\\python.exe -m pip install ."
build: off
test_script:
- "%PYTHON%\\python.exe -m pyfakefs.tests.all_tests"
- "%PYTHON%\\python.exe -m pyfakefs.tests.all_tests_without_extra_packages"
- "%PYTHON%\\python.exe -m pytest pyfakefs\\tests\\pytest\\pytest_plugin_test.py"
- IF "C:\\Python36-x64"=="%PYTHON%" "%PYTHON%\\python.exe -m pytest pyfakefs\\tests\\pytest\\pytest_fixture_test.py"
- "%PYTHON%\\python.exe -m pytest pyfakefs\\tests\\pytest\\pytest_plugin_failing_test.py > testresult.txt | echo."
View
@@ -0,0 +1,13 @@
# "pathlib2" and "scandir" are backports of new standard modules, pyfakefs will
# use them if available when running on older Python versions.
#
# They are dependencies of pytest when Python < 3.6 so we sometimes get them via
# requirements.txt, this file makes them explicit dependencies for testing &
# development.
#
# Older versions might work ok, the versions chosen here are just the latest
# available at the time of writing.
pathlib2>=2.3.2
scandir>=1.8
View
@@ -0,0 +1,24 @@
try:
import pathlib
pathlib2 = None
except ImportError:
try:
import pathlib2
pathlib = pathlib2
except ImportError:
pathlib = None
pathlib2 = None
try:
from os import scandir
use_scandir = True
use_scandir_package = False
except ImportError:
try:
import scandir
use_scandir = True
use_scandir_package = True
except ImportError:
use_scandir = False
use_scandir_package = False
@@ -107,9 +107,10 @@
from pyfakefs.deprecator import Deprecator
from pyfakefs.fake_scandir import scandir, walk
from pyfakefs.extra_packages import use_scandir
from pyfakefs.helpers import FakeStatResult, FileBufferIO, IS_PY2, NullFileBufferIO
from pyfakefs.helpers import is_int_type, is_byte_string, is_unicode_string
from pyfakefs.helpers import make_string_path
from pyfakefs.helpers import make_string_path, text_type
__pychecker__ = 'no-reimportself'
@@ -122,11 +123,6 @@
PERM_DEF_FILE = 0o666 # Default permission bits (regular file)
PERM_ALL = 0o7777 # All permission bits.
try:
text_type = unicode # Python 2
except NameError:
text_type = str # Python 3
_OpenModes = namedtuple(
'open_modes',
'must_exist can_read can_write truncate append must_not_exist'
@@ -3693,7 +3689,7 @@ def listxattr(self, path=None, follow_symlinks=True):
used by shutil."""
return []
if sys.version_info >= (3, 5):
if use_scandir:
def scandir(self, path=''):
"""Return an iterator of DirEntry objects corresponding to the
entries in the directory given by path.
@@ -63,17 +63,13 @@
from pyfakefs import fake_filesystem
from pyfakefs import fake_filesystem_shutil
from pyfakefs import mox3_stubout
from pyfakefs.extra_packages import pathlib, use_scandir
if sys.version_info >= (3, 4):
if pathlib:
from pyfakefs import fake_pathlib
try:
import scandir # noqa: F401 import used to set has_scandir
import fake_scandir
has_scandir = True
except ImportError:
has_scandir = False
if use_scandir:
from pyfakefs import fake_scandir
if sys.version_info < (3, ):
import __builtin__ as builtins # pylint: disable=import-error
@@ -284,11 +280,10 @@ class Patcher(object):
assert None in SKIPMODULES, ("sys.modules contains 'None' values;"
" must skip them.")
HAS_PATHLIB = sys.version_info >= (3, 4)
IS_WINDOWS = sys.platform in ('win32', 'cygwin')
SKIPNAMES = {'os', 'path', 'io', 'genericpath'}
if HAS_PATHLIB:
if pathlib:
SKIPNAMES.add('pathlib')
def __init__(self, additional_skip_names=None, patch_path=True,
@@ -321,10 +316,10 @@ def __init__(self, additional_skip_names=None, patch_path=True,
'shutil': fake_filesystem_shutil.FakeShutilModule,
'io': fake_filesystem.FakeIoModule,
}
if self.HAS_PATHLIB:
if pathlib:
self._fake_module_classes[
'pathlib'] = fake_pathlib.FakePathlibModule
if has_scandir:
if use_scandir:
self._fake_module_classes[
'scandir'] = fake_scandir.FakeScanDirModule
View
@@ -30,8 +30,11 @@
"""
import os
import pathlib
from urllib.parse import quote_from_bytes as urlquote_from_bytes
try:
from urllib.parse import quote_from_bytes as urlquote_from_bytes
except ImportError:
from urllib import quote as urlquote_from_bytes
import sys
@@ -40,6 +43,8 @@
import errno
from pyfakefs import fake_scandir
from pyfakefs.extra_packages import use_scandir, pathlib, pathlib2
from pyfakefs.helpers import text_type
from pyfakefs.fake_filesystem import FakeFileOpen, FakeFilesystem
@@ -91,7 +96,7 @@ class _FakeAccessor(pathlib._Accessor): # pylint: disable=protected-access
chmod = _wrap_strfunc(FakeFilesystem.chmod)
if sys.version_info >= (3, 6):
if use_scandir:
scandir = _wrap_strfunc(fake_scandir.scandir)
if hasattr(os, "lchmod"):
@@ -280,13 +285,13 @@ def _resolve_windows(self, path, strict):
previous_s = None
if strict:
if not self.filesystem.exists(path):
raise FileNotFoundError(path)
self.filesystem.raise_os_error(errno.ENOENT, path)
return self.filesystem.resolve_path(path)
else:
while True:
try:
path = self.filesystem.resolve_path(path)
except FileNotFoundError:
except IOError:
previous_s = path
path = self.filesystem.splitpath(path)[0]
else:
@@ -472,11 +477,14 @@ def resolve(self, strict=None):
Raises:
IOError: if the path doesn't exist (strict=True or Python < 3.6)
"""
if strict is None:
strict = sys.version_info < (3, 6)
elif sys.version_info < (3, 6):
raise TypeError(
"resolve() got an unexpected keyword argument 'strict'")
if sys.version_info >= (3, 6) or pathlib2:
if strict is None:
strict = False
else:
if strict is not None:
raise TypeError(
"resolve() got an unexpected keyword argument 'strict'")
strict = True
if self._closed:
self._raise_closed()
path = self._flavour.resolve(self, strict=strict)
@@ -496,10 +504,10 @@ def open(self, mode='r', buffering=-1, encoding=None,
"""
if self._closed:
self._raise_closed()
return FakeFileOpen(self.filesystem)(
return FakeFileOpen(self.filesystem, use_io=True)(
self._path(), mode, buffering, encoding, errors, newline)
if sys.version_info >= (3, 5):
if sys.version_info >= (3, 5) or pathlib2:
def read_bytes(self):
"""Open the fake file in bytes mode, read it, and close the file.
@@ -514,7 +522,7 @@ def read_text(self, encoding=None, errors=None):
"""
Open the fake file in text mode, read it, and close the file.
"""
with FakeFileOpen(self.filesystem)(self._path(), mode='r',
with FakeFileOpen(self.filesystem, use_io=True)(self._path(), mode='r',
encoding=encoding,
errors=errors) as f:
return f.read()
@@ -542,14 +550,15 @@ def write_text(self, data, encoding=None, errors=None):
default locale encoding is used
errors: ignored
Raises:
TypeError: if data is not of type 'str'
TypeError: if data is not of type 'str' (Python 3) or 'unicode'
(Python 2)
IOError: if the target object is a directory, the path is
invalid or permission is denied.
"""
if not isinstance(data, str):
if not isinstance(data, text_type):
raise TypeError('data must be str, not %s' %
data.__class__.__name__)
with FakeFileOpen(self.filesystem)(self._path(), mode='w',
with FakeFileOpen(self.filesystem, use_io=True)(self._path(), mode='w',
encoding=encoding,
errors=errors) as f:
return f.write(data)
@@ -599,15 +608,17 @@ def touch(self, mode=0o666, exist_ok=True):
happens, otherwise FileExistError is raised
Raises:
FileExistsError if the file exists and exits_ok is False.
OSError: (Python 2 only) if the file exists and exits_ok is False.
FileExistsError: (Python 3 only) if the file exists and exits_ok is
False.
"""
if self._closed:
self._raise_closed()
if self.exists():
if exist_ok:
self.filesystem.utime(self._path(), None)
else:
raise FileExistsError
self.filesystem.raise_os_error(errno.EEXIST, self._path())
else:
fake_file = self.open('w')
fake_file.close()
View
@@ -18,6 +18,8 @@
"""
import sys
from pyfakefs.extra_packages import use_scandir_package
class DirEntry(object):
"""Emulates os.DirEntry. Note that we did not enforce keyword only
@@ -107,7 +109,8 @@ 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:
if not use_scandir_package and (
sys.version_info < (3, 7) or self.filesystem.is_windows_fs):
raise NotImplementedError(
'scandir does not support file descriptor '
'path argument')
View
@@ -22,6 +22,12 @@
IS_PY2 = sys.version_info[0] < 3
try:
text_type = unicode # Python 2
except NameError:
text_type = str # Python 3
def is_int_type(val):
"""Return True if `val` is of integer type."""
try: # Python 2
@@ -35,7 +41,7 @@ def is_byte_string(val):
string."""
if not IS_PY2:
return not hasattr(val, 'encode')
return isinstance(val, str)
return isinstance(val, (memoryview, str))
def is_unicode_string(val):
@@ -19,6 +19,7 @@
import sys
import unittest
from pyfakefs.extra_packages import pathlib
from pyfakefs.tests import dynamic_patch_test
from pyfakefs.tests import fake_open_test
from pyfakefs.tests import fake_os_test
@@ -31,7 +32,7 @@
from pyfakefs.tests import fake_filesystem_vs_real_test
from pyfakefs.tests import mox3_stubout_test
if sys.version_info >= (3, 4):
if pathlib:
from pyfakefs.tests import fake_pathlib_test
@@ -53,7 +54,7 @@ def suite(self): # pylint: disable-msg=C6409
loader.loadTestsFromModule(mox3_stubout_test),
loader.loadTestsFromModule(dynamic_patch_test),
])
if sys.version_info >= (3, 4):
if pathlib:
self.addTests([
loader.loadTestsFromModule(fake_pathlib_test)
])
@@ -0,0 +1,19 @@
import sys
import unittest
from pyfakefs import extra_packages
if extra_packages.pathlib2:
extra_packages.pathlib = None
extra_packages.pathlib2 = None
if extra_packages.use_scandir_package:
extra_packages.use_scandir = False
extra_packages.use_scandir_package = False
from pyfakefs.tests.all_tests import AllTests
if __name__ == '__main__':
result = unittest.TextTestRunner(verbosity=2).run(AllTests().suite())
sys.exit(int(not result.wasSuccessful()))
@@ -17,6 +17,7 @@
import unittest
from pyfakefs import fake_filesystem_unittest
from pyfakefs.extra_packages import pathlib
class TestPyfakefsUnittestBase(fake_filesystem_unittest.TestCase):
@@ -60,10 +61,8 @@ def test_shutil_patch(self):
self.fs.set_disk_usage(100)
self.assertEqual(100, shutil.disk_usage('/').total)
@unittest.skipIf(sys.version_info < (3, 4), 'pathlib new in Python 3.4')
@unittest.skipIf(not pathlib, 'only run if pathlib is available')
def test_pathlib_patch(self):
import pathlib
file_path = 'test.txt'
path = pathlib.Path(file_path)
with path.open('w') as f:
@@ -73,12 +72,10 @@ def test_pathlib_patch(self):
file_object = self.fs.get_object(file_path)
self.assertEqual('test', file_object.contents)
@unittest.skipIf(sys.version_info < (3, 4), 'pathlib new in Python 3.4')
@unittest.skipIf(not pathlib, 'only run if pathlib is available')
def test_pathlib_path_patch(self):
from pathlib import Path
file_path = 'test.txt'
path = Path(file_path)
path = pathlib.Path(file_path)
with path.open('w') as f:
f.write('test')
Oops, something went wrong.

0 comments on commit 05e7d2a

Please sign in to comment.