@@ -197,7 +197,7 @@ def prepare_path(pth):
197197 if not isinstance (pth , bytes ):
198198 pth = fsencode (pth )
199199 return pth
200- else :
200+ else :
201201 if not isinstance (pth , compat .unicode ):
202202 return fsdecode (pth )
203203 return pth
@@ -365,12 +365,12 @@ def ignore_nothing(_):
365365 return False
366366
367367
368- def walk (location , ignored = None ):
368+ def walk (location , ignored = None , allow_symlinks = False ):
369369 """
370370 Walk location returning the same tuples as os.walk but with a different
371371 behavior:
372372 - always walk top-down, breadth-first.
373- - always ignore and never follow symlinks,
373+ - always ignore and never follow symlinks (unless `allow_symlinks` is True) ,
374374 - always ignore special files (FIFOs, etc.)
375375 - optionally ignore files and directories by invoking the `ignored`
376376 callable on files and directories returning True if it should be ignored.
@@ -387,33 +387,38 @@ def walk(location, ignored=None):
387387 logger_debug ('walk: ignored:' , location , is_ignored )
388388 return
389389
390- if filetype .is_file (location ) :
390+ if filetype .is_file (location , allow_symlinks = allow_symlinks ) :
391391 yield parent_directory (location ), [], [file_name (location )]
392392
393- elif filetype .is_dir (location ):
393+ elif filetype .is_dir (location , allow_symlinks = allow_symlinks ):
394394 dirs = []
395395 files = []
396396 # TODO: consider using scandir
397397 for name in os .listdir (location ):
398398 loc = os .path .join (location , name )
399399 if filetype .is_special (loc ) or (ignored and ignored (loc )):
400- if TRACE :
401- ign = ignored and ignored (loc )
402- logger_debug ('walk: ignored:' , loc , ign )
403- continue
400+ if (allow_symlinks
401+ and filetype .is_link (loc )
402+ and not filetype .is_broken_link (location )):
403+ pass
404+ else :
405+ if TRACE :
406+ ign = ignored and ignored (loc )
407+ logger_debug ('walk: ignored:' , loc , ign )
408+ continue
404409 # special files and symlinks are always ignored
405- if filetype .is_dir (loc ):
410+ if filetype .is_dir (loc , allow_symlinks = allow_symlinks ):
406411 dirs .append (name )
407- elif filetype .is_file (loc ):
412+ elif filetype .is_file (loc , allow_symlinks = allow_symlinks ):
408413 files .append (name )
409414 yield location , dirs , files
410415
411416 for dr in dirs :
412- for tripple in walk (os .path .join (location , dr ), ignored ):
417+ for tripple in walk (os .path .join (location , dr ), ignored , allow_symlinks = allow_symlinks ):
413418 yield tripple
414419
415420
416- def resource_iter (location , ignored = ignore_nothing , with_dirs = True ):
421+ def resource_iter (location , ignored = ignore_nothing , with_dirs = True , allow_symlinks = False ):
417422 """
418423 Return an iterable of paths at `location` recursively.
419424
@@ -424,7 +429,7 @@ def resource_iter(location, ignored=ignore_nothing, with_dirs=True):
424429 """
425430 if on_linux and py2 :
426431 location = fsencode (location )
427- for top , dirs , files in walk (location , ignored ):
432+ for top , dirs , files in walk (location , ignored , allow_symlinks = allow_symlinks ):
428433 if with_dirs :
429434 for d in dirs :
430435 yield os .path .join (top , d )
0 commit comments