@@ -88,12 +88,15 @@ def _do_cmp(f1, f2):
8888class dircmp :
8989 """A class that manages the comparison of 2 directories.
9090
91- dircmp(a, b, ignore=None, hide=None)
91+ dircmp(a, b, ignore=None, hide=None, *, shallow=True )
9292 A and B are directories.
9393 IGNORE is a list of names to ignore,
9494 defaults to DEFAULT_IGNORES.
9595 HIDE is a list of names to hide,
9696 defaults to [os.curdir, os.pardir].
97+ SHALLOW specifies whether to just check the stat signature (do not read
98+ the files).
99+ defaults to True.
97100
98101 High level usage:
99102 x = dircmp(dir1, dir2)
@@ -121,7 +124,7 @@ class dircmp:
121124 in common_dirs.
122125 """
123126
124- def __init__ (self , a , b , ignore = None , hide = None ): # Initialize
127+ def __init__ (self , a , b , ignore = None , hide = None , * , shallow = True ): # Initialize
125128 self .left = a
126129 self .right = b
127130 if hide is None :
@@ -132,6 +135,7 @@ def __init__(self, a, b, ignore=None, hide=None): # Initialize
132135 self .ignore = DEFAULT_IGNORES
133136 else :
134137 self .ignore = ignore
138+ self .shallow = shallow
135139
136140 def phase0 (self ): # Compare everything except common subdirectories
137141 self .left_list = _filter (os .listdir (self .left ),
@@ -160,12 +164,14 @@ def phase2(self): # Distinguish files, directories, funnies
160164 ok = True
161165 try :
162166 a_stat = os .stat (a_path )
163- except OSError :
167+ except (OSError , ValueError ):
168+ # See https://github.com/python/cpython/issues/122400
169+ # for the rationale for protecting against ValueError.
164170 # print('Can\'t stat', a_path, ':', why.args[1])
165171 ok = False
166172 try :
167173 b_stat = os .stat (b_path )
168- except OSError :
174+ except ( OSError , ValueError ) :
169175 # print('Can\'t stat', b_path, ':', why.args[1])
170176 ok = False
171177
@@ -184,7 +190,7 @@ def phase2(self): # Distinguish files, directories, funnies
184190 self .common_funny .append (x )
185191
186192 def phase3 (self ): # Find out differences between common files
187- xx = cmpfiles (self .left , self .right , self .common_files )
193+ xx = cmpfiles (self .left , self .right , self .common_files , self . shallow )
188194 self .same_files , self .diff_files , self .funny_files = xx
189195
190196 def phase4 (self ): # Find out differences between common subdirectories
@@ -196,7 +202,8 @@ def phase4(self): # Find out differences between common subdirectories
196202 for x in self .common_dirs :
197203 a_x = os .path .join (self .left , x )
198204 b_x = os .path .join (self .right , x )
199- self .subdirs [x ] = self .__class__ (a_x , b_x , self .ignore , self .hide )
205+ self .subdirs [x ] = self .__class__ (a_x , b_x , self .ignore , self .hide ,
206+ shallow = self .shallow )
200207
201208 def phase4_closure (self ): # Recursively call phase4() on subdirectories
202209 self .phase4 ()
@@ -280,12 +287,12 @@ def cmpfiles(a, b, common, shallow=True):
280287# Return:
281288# 0 for equal
282289# 1 for different
283- # 2 for funny cases (can't stat, etc.)
290+ # 2 for funny cases (can't stat, NUL bytes, etc.)
284291#
285292def _cmp (a , b , sh , abs = abs , cmp = cmp ):
286293 try :
287294 return not abs (cmp (a , b , sh ))
288- except OSError :
295+ except ( OSError , ValueError ) :
289296 return 2
290297
291298
0 commit comments