@ -163,6 +163,8 @@ def command_sanity(args):
else :
raise Exception ( ' Unsupported test type: %s ' % type ( test ) )
all_targets = targets . targets
if test . all_targets :
usable_targets = targets . targets
elif test . no_targets :
@ -170,12 +172,12 @@ def command_sanity(args):
else :
usable_targets = targets . include
if test . include_directories :
usable_targets + = tuple ( TestTarget ( path , None , None , ' ' ) for path in paths_to_dirs ( [ target . path for target in usable_targets ] ) )
all_targets = SanityTargets . filter_and_inject_targets ( test , all_targets )
usable_targets = SanityTargets . filter_and_inject_targets ( test , usable_targets )
usable_targets = sorted ( test . filter_targets ( list ( usable_targets ) ) )
usable_targets = settings . filter_skipped_targets ( usable_targets )
sanity_targets = SanityTargets ( targets . targets , tuple ( usable_targets ) )
sanity_targets = SanityTargets ( tuple ( all_targets ) , tuple ( usable_targets ) )
if usable_targets or test . no_targets :
if isinstance ( test , SanityCodeSmellTest ) :
@ -266,10 +268,7 @@ class SanityIgnoreParser:
display . info ( ' Read %d sanity test ignore line(s) for %s from: %s ' % ( len ( lines ) , ansible_label , self . relative_path ) , verbosity = 1 )
for test in sanity_get_tests ( ) :
test_targets = list ( targets )
if test . include_directories :
test_targets + = tuple ( TestTarget ( path , None , None , ' ' ) for path in paths_to_dirs ( [ target . path for target in test_targets ] ) )
test_targets = SanityTargets . filter_and_inject_targets ( test , targets )
paths_by_test [ test . name ] = set ( target . path for target in test . filter_targets ( test_targets ) )
@ -488,10 +487,9 @@ class SanityIgnoreProcessor:
if self . test . no_targets or self . test . all_targets :
# tests which do not accept a target list, or which use all targets, always return all possible errors, so all ignores can be checked
paths = [ target . path for target in SanityTargets . get_targets ( ) ]
if self . test . include_directories :
paths . extend ( paths_to_dirs ( paths ) )
targets = SanityTargets . get_targets ( )
test_targets = SanityTargets . filter_and_inject_targets ( self . test , targets )
paths = [ target . path for target in test_targets ]
for path in paths :
path_entry = self . ignore_entries . get ( path )
@ -562,6 +560,29 @@ class SanityTargets:
_include = walk_internal_targets ( _targets , include , exclude , require )
return SanityTargets ( _targets , _include )
@staticmethod
def filter_and_inject_targets ( test , targets ) : # type: (SanityTest, t.Iterable[TestTarget]) -> t.List[TestTarget]
""" Filter and inject targets based on test requirements and the given target list. """
test_targets = list ( targets )
if not test . include_symlinks :
# remove all symlinks unless supported by the test
test_targets = [ target for target in test_targets if not target . symlink ]
if not test . include_directories or not test . include_symlinks :
# exclude symlinked directories unless supported by the test
test_targets = [ target for target in test_targets if not target . path . endswith ( os . path . sep ) ]
if test . include_directories :
# include directories containing any of the included files
test_targets + = tuple ( TestTarget ( path , None , None , ' ' ) for path in paths_to_dirs ( [ target . path for target in test_targets ] ) )
if not test . include_symlinks :
# remove all directory symlinks unless supported by the test
test_targets = [ target for target in test_targets if not target . symlink ]
return test_targets
@staticmethod
def get_targets ( ) : # type: () -> t.Tuple[TestTarget, ...]
""" Return a tuple of sanity test targets. Uses a cached version when available. """
@ -613,6 +634,11 @@ class SanityTest(ABC):
""" True if the test targets should include directories. """
return False
@property
def include_symlinks ( self ) : # type: () -> bool
""" True if the test targets should include symlinks. """
return False
@property
def supported_python_versions ( self ) : # type: () -> t.Optional[t.Tuple[str, ...]]
""" A tuple of supported Python versions or None if the test does not depend on specific Python versions. """
@ -655,6 +681,7 @@ class SanityCodeSmellTest(SanityTest):
self . __all_targets = self . config . get ( ' all_targets ' ) # type: bool
self . __no_targets = self . config . get ( ' no_targets ' ) # type: bool
self . __include_directories = self . config . get ( ' include_directories ' ) # type: bool
self . __include_symlinks = self . config . get ( ' include_symlinks ' ) # type: bool
else :
self . output = None
self . extensions = [ ]
@ -666,6 +693,7 @@ class SanityCodeSmellTest(SanityTest):
self . __all_targets = False
self . __no_targets = True
self . __include_directories = False
self . __include_symlinks = False
if self . no_targets :
mutually_exclusive = (
@ -676,6 +704,7 @@ class SanityCodeSmellTest(SanityTest):
' ignore_self ' ,
' all_targets ' ,
' include_directories ' ,
' include_symlinks ' ,
)
problems = sorted ( name for name in mutually_exclusive if getattr ( self , name ) )
@ -698,6 +727,11 @@ class SanityCodeSmellTest(SanityTest):
""" True if the test targets should include directories. """
return self . __include_directories
@property
def include_symlinks ( self ) : # type: () -> bool
""" True if the test targets should include symlinks. """
return self . __include_symlinks
def filter_targets ( self , targets ) : # type: (t.List[TestTarget]) -> t.List[TestTarget]
""" Return the given list of test targets, filtered to include only those relevant for the test. """
if self . no_targets :