107
107
108
108
from pyfakefs .deprecator import Deprecator
109
109
from pyfakefs .fake_scandir import scandir , walk
110
- from pyfakefs .helpers import FakeStatResult , FileBufferIO , IS_PY2
110
+ from pyfakefs .helpers import FakeStatResult , FileBufferIO , IS_PY2 , NullFileBufferIO
111
111
from pyfakefs .helpers import is_int_type , is_byte_string , is_unicode_string
112
112
from pyfakefs .helpers import make_string_path
113
113
@@ -498,6 +498,19 @@ def SetIno(self, st_ino):
498
498
self .st_ino = st_ino
499
499
500
500
501
+ class FakeNullFile (FakeFile ):
502
+ def __init__ (self , filesystem ):
503
+ devnull = '/dev/nul' if filesystem .is_windows_fs else '/dev/nul'
504
+ super (FakeNullFile , self ).__init__ (devnull , filesystem = filesystem , contents = b'' )
505
+
506
+ @property
507
+ def byte_contents (self ):
508
+ return b''
509
+
510
+ def _set_initial_contents (self , contents ):
511
+ pass
512
+
513
+
501
514
Deprecator .add (FakeFile , FakeFile .set_large_file_size , 'SetLargeFileSize' )
502
515
Deprecator .add (FakeFile , FakeFile .set_contents , 'SetContents' )
503
516
Deprecator .add (FakeFile , FakeFile .is_large_file , 'IsLargeFile' )
@@ -825,6 +838,7 @@ def __init__(self, path_separator=os.path.sep, total_size=None):
825
838
self .mount_points = {}
826
839
self .add_mount_point (self .root .name , total_size )
827
840
self ._add_standard_streams ()
841
+ self .dev_null = FakeNullFile (self )
828
842
829
843
def reset (self , total_size = None ):
830
844
"""Remove all file system contents and reset the root."""
@@ -1663,6 +1677,8 @@ def exists(self, file_path, check_link=False):
1663
1677
raise TypeError
1664
1678
if not file_path :
1665
1679
return False
1680
+ if file_path == self .dev_null .name :
1681
+ return not self .is_windows_fs
1666
1682
try :
1667
1683
if self .is_filepath_ending_with_separator (file_path ):
1668
1684
return False
@@ -1740,7 +1756,8 @@ def resolve_path(self, file_path, allow_fd=False, raw_io=True):
1740
1756
file_path = self .absnormpath (self ._original_path (file_path ))
1741
1757
if self ._is_root_path (file_path ):
1742
1758
return file_path
1743
-
1759
+ if file_path == self .dev_null .name :
1760
+ return file_path
1744
1761
path_components = self ._path_components (file_path )
1745
1762
resolved_components = self ._resolve_components (path_components , raw_io )
1746
1763
return self ._components_to_path (resolved_components )
@@ -1861,6 +1878,8 @@ def get_object_from_normpath(self, file_path):
1861
1878
file_path = make_string_path (file_path )
1862
1879
if file_path == self .root .name :
1863
1880
return self .root
1881
+ if file_path == self .dev_null .name :
1882
+ return self .dev_null
1864
1883
1865
1884
file_path = self ._original_path (file_path )
1866
1885
path_components = self ._path_components (file_path )
@@ -3360,6 +3379,8 @@ class FakeOsModule(object):
3360
3379
my_os_module = fake_filesystem.FakeOsModule(filesystem)
3361
3380
"""
3362
3381
3382
+ devnull = None
3383
+
3363
3384
def __init__ (self , filesystem , os_path_module = None ):
3364
3385
"""Also exposes self.path (to fake os.path).
3365
3386
@@ -3382,6 +3403,8 @@ def __init__(self, filesystem, os_path_module=None):
3382
3403
self .fdopen = self ._fdopen_ver2
3383
3404
else :
3384
3405
self .fdopen = self ._fdopen
3406
+ self .__class__ .devnull = ('/dev/nul' if filesystem .is_windows_fs
3407
+ else '/dev/nul' )
3385
3408
3386
3409
def _fdopen (self , * args , ** kwargs ):
3387
3410
"""Redirector to open() builtin function.
@@ -3506,7 +3529,8 @@ def open(self, file_path, flags, mode=None, dir_fd=None):
3506
3529
fake_file = FakeFileOpen (
3507
3530
self .filesystem , delete_on_close = delete_on_close , raw_io = True )(
3508
3531
file_path , str_flags , open_modes = open_modes )
3509
- self .chmod (file_path , mode )
3532
+ if fake_file .file_object != self .filesystem .dev_null :
3533
+ self .chmod (file_path , mode )
3510
3534
return fake_file .fileno ()
3511
3535
3512
3536
def close (self , file_des ):
@@ -4294,7 +4318,9 @@ def __init__(self, file_object, file_path, update=False, read=False,
4294
4318
contents = file_object .byte_contents
4295
4319
self ._encoding = encoding or locale .getpreferredencoding (False )
4296
4320
errors = errors or 'strict'
4297
- self ._io = FileBufferIO (contents , linesep = filesystem .line_separator (),
4321
+ buffer_class = (NullFileBufferIO if file_object == filesystem .dev_null
4322
+ else FileBufferIO )
4323
+ self ._io = buffer_class (contents , linesep = filesystem .line_separator (),
4298
4324
binary = binary , encoding = encoding ,
4299
4325
newline = newline , errors = errors )
4300
4326
@@ -4868,11 +4894,15 @@ def _handle_file_arg(self, file_):
4868
4894
# open a file file by path
4869
4895
filedes = None
4870
4896
file_path = file_
4871
- real_path = self .filesystem .resolve_path (
4872
- file_path , raw_io = self .raw_io )
4873
- if self .filesystem .exists (file_path ):
4874
- file_object = self .filesystem .get_object_from_normpath (
4875
- real_path )
4897
+ if file_path == self .filesystem .dev_null .name :
4898
+ file_object = self .filesystem .dev_null
4899
+ real_path = file_path
4900
+ else :
4901
+ real_path = self .filesystem .resolve_path (
4902
+ file_path , raw_io = self .raw_io )
4903
+ if self .filesystem .exists (file_path ):
4904
+ file_object = self .filesystem .get_object_from_normpath (
4905
+ real_path )
4876
4906
return file_object , file_path , filedes , real_path
4877
4907
4878
4908
def _handle_file_mode (self , mode , newline , open_modes ):
0 commit comments