@ -163,6 +163,8 @@ def command_sanity(args):
else :
else :
raise Exception ( ' Unsupported test type: %s ' % type ( test ) )
raise Exception ( ' Unsupported test type: %s ' % type ( test ) )
all_targets = targets . targets
if test . all_targets :
if test . all_targets :
usable_targets = targets . targets
usable_targets = targets . targets
elif test . no_targets :
elif test . no_targets :
@ -170,12 +172,12 @@ def command_sanity(args):
else :
else :
usable_targets = targets . include
usable_targets = targets . include
if test . include_directories :
all_targets = SanityTargets . filter_and_inject_targets ( test , all_targets )
usable_targets + = tuple ( TestTarget ( path , None , None , ' ' ) for path in paths_to_dirs ( [ target . path for target in usable_targets ] ) )
usable_targets = SanityTargets . filter_and_inject_targets ( test , usable_targets )
usable_targets = sorted ( test . filter_targets ( list ( usable_targets ) ) )
usable_targets = sorted ( test . filter_targets ( list ( usable_targets ) ) )
usable_targets = settings . filter_skipped_targets ( 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 usable_targets or test . no_targets :
if isinstance ( test , SanityCodeSmellTest ) :
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 )
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 ( ) :
for test in sanity_get_tests ( ) :
test_targets = list ( targets )
test_targets = SanityTargets . filter_and_inject_targets ( test , 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 ] ) )
paths_by_test [ test . name ] = set ( target . path for target in test . filter_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 :
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
# 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 ( ) ]
targets = SanityTargets . get_targets ( )
test_targets = SanityTargets . filter_and_inject_targets ( self . test , targets )
if self . test . include_directories :
paths = [ target . path for target in test_targets ]
paths . extend ( paths_to_dirs ( paths ) )
for path in paths :
for path in paths :
path_entry = self . ignore_entries . get ( path )
path_entry = self . ignore_entries . get ( path )
@ -562,6 +560,29 @@ class SanityTargets:
_include = walk_internal_targets ( _targets , include , exclude , require )
_include = walk_internal_targets ( _targets , include , exclude , require )
return SanityTargets ( _targets , _include )
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
@staticmethod
def get_targets ( ) : # type: () -> t.Tuple[TestTarget, ...]
def get_targets ( ) : # type: () -> t.Tuple[TestTarget, ...]
""" Return a tuple of sanity test targets. Uses a cached version when available. """
""" 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. """
""" True if the test targets should include directories. """
return False
return False
@property
def include_symlinks ( self ) : # type: () -> bool
""" True if the test targets should include symlinks. """
return False
@property
@property
def supported_python_versions ( self ) : # type: () -> t.Optional[t.Tuple[str, ...]]
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. """
""" 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 . __all_targets = self . config . get ( ' all_targets ' ) # type: bool
self . __no_targets = self . config . get ( ' no_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_directories = self . config . get ( ' include_directories ' ) # type: bool
self . __include_symlinks = self . config . get ( ' include_symlinks ' ) # type: bool
else :
else :
self . output = None
self . output = None
self . extensions = [ ]
self . extensions = [ ]
@ -666,6 +693,7 @@ class SanityCodeSmellTest(SanityTest):
self . __all_targets = False
self . __all_targets = False
self . __no_targets = True
self . __no_targets = True
self . __include_directories = False
self . __include_directories = False
self . __include_symlinks = False
if self . no_targets :
if self . no_targets :
mutually_exclusive = (
mutually_exclusive = (
@ -676,6 +704,7 @@ class SanityCodeSmellTest(SanityTest):
' ignore_self ' ,
' ignore_self ' ,
' all_targets ' ,
' all_targets ' ,
' include_directories ' ,
' include_directories ' ,
' include_symlinks ' ,
)
)
problems = sorted ( name for name in mutually_exclusive if getattr ( self , name ) )
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. """
""" True if the test targets should include directories. """
return self . __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]
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. """
""" Return the given list of test targets, filtered to include only those relevant for the test. """
if self . no_targets :
if self . no_targets :