@ -11,12 +11,7 @@ import tempfile
import time
import time
import textwrap
import textwrap
import functools
import functools
import shutil
import stat
import pipes
import pipes
import random
import string
import atexit
import hashlib
import hashlib
import lib . pytar
import lib . pytar
@ -45,11 +40,12 @@ from lib.util import (
SubprocessError ,
SubprocessError ,
display ,
display ,
run_command ,
run_command ,
common_environment ,
intercept_command ,
remove_tree ,
remove_tree ,
make_dirs ,
make_dirs ,
is_shippable ,
is_shippable ,
is_binary_file ,
is_binary_file ,
find_pip ,
find_executable ,
find_executable ,
raw_command ,
raw_command ,
)
)
@ -110,8 +106,6 @@ SUPPORTED_PYTHON_VERSIONS = (
COMPILE_PYTHON_VERSIONS = SUPPORTED_PYTHON_VERSIONS
COMPILE_PYTHON_VERSIONS = SUPPORTED_PYTHON_VERSIONS
coverage_path = ' ' # pylint: disable=locally-disabled, invalid-name
def check_startup ( ) :
def check_startup ( ) :
""" Checks to perform at startup before running commands. """
""" Checks to perform at startup before running commands. """
@ -163,23 +157,27 @@ def install_command_requirements(args):
if args . junit :
if args . junit :
packages . append ( ' junit-xml ' )
packages . append ( ' junit-xml ' )
commands = [ generate_pip_install ( args . command , packages = packages ) ]
pip = find_pip ( version = args . python_version )
commands = [ generate_pip_install ( pip , args . command , packages = packages ) ]
if isinstance ( args , IntegrationConfig ) :
if isinstance ( args , IntegrationConfig ) :
for cloud_platform in get_cloud_platforms ( args ) :
for cloud_platform in get_cloud_platforms ( args ) :
commands . append ( generate_pip_install ( ' %s .cloud. %s ' % ( args . command , cloud_platform ) ) )
commands . append ( generate_pip_install ( pip , ' %s .cloud. %s ' % ( args . command , cloud_platform ) ) )
commands = [ cmd for cmd in commands if cmd ]
# only look for changes when more than one requirements file is needed
# only look for changes when more than one requirements file is needed
detect_pip_changes = len ( commands ) > 1
detect_pip_changes = len ( commands ) > 1
# first pass to install requirements, changes expected unless environment is already set up
# first pass to install requirements, changes expected unless environment is already set up
changes = run_pip_commands ( args , commands, detect_pip_changes )
changes = run_pip_commands ( args , pip, commands, detect_pip_changes )
if not changes :
if not changes :
return # no changes means we can stop early
return # no changes means we can stop early
# second pass to check for conflicts in requirements, changes are not expected here
# second pass to check for conflicts in requirements, changes are not expected here
changes = run_pip_commands ( args , commands, detect_pip_changes )
changes = run_pip_commands ( args , pip, commands, detect_pip_changes )
if not changes :
if not changes :
return # no changes means no conflicts
return # no changes means no conflicts
@ -188,16 +186,17 @@ def install_command_requirements(args):
' \n ' . join ( ( ' ' . join ( pipes . quote ( c ) for c in cmd ) for cmd in changes ) ) )
' \n ' . join ( ( ' ' . join ( pipes . quote ( c ) for c in cmd ) for cmd in changes ) ) )
def run_pip_commands ( args , commands, detect_pip_changes = False ) :
def run_pip_commands ( args , pip, commands, detect_pip_changes = False ) :
"""
"""
: type args : EnvironmentConfig
: type args : EnvironmentConfig
: type pip : str
: type commands : list [ list [ str ] ]
: type commands : list [ list [ str ] ]
: type detect_pip_changes : bool
: type detect_pip_changes : bool
: rtype : list [ list [ str ] ]
: rtype : list [ list [ str ] ]
"""
"""
changes = [ ]
changes = [ ]
after_list = pip_list ( args ) if detect_pip_changes else None
after_list = pip_list ( args , pip ) if detect_pip_changes else None
for cmd in commands :
for cmd in commands :
if not cmd :
if not cmd :
@ -217,10 +216,10 @@ def run_pip_commands(args, commands, detect_pip_changes=False):
# AttributeError: 'Requirement' object has no attribute 'project_name'
# AttributeError: 'Requirement' object has no attribute 'project_name'
# See: https://bugs.launchpad.net/ubuntu/xenial/+source/python-pip/+bug/1626258
# See: https://bugs.launchpad.net/ubuntu/xenial/+source/python-pip/+bug/1626258
# Upgrading pip works around the issue.
# Upgrading pip works around the issue.
run_command ( args , [ ' pip ' , ' install ' , ' --upgrade ' , ' pip ' ] )
run_command ( args , [ pip , ' install ' , ' --upgrade ' , ' pip ' ] )
run_command ( args , cmd )
run_command ( args , cmd )
after_list = pip_list ( args ) if detect_pip_changes else None
after_list = pip_list ( args , pip ) if detect_pip_changes else None
if before_list != after_list :
if before_list != after_list :
changes . append ( cmd )
changes . append ( cmd )
@ -228,12 +227,13 @@ def run_pip_commands(args, commands, detect_pip_changes=False):
return changes
return changes
def pip_list ( args ):
def pip_list ( args , pip ):
"""
"""
: type args : EnvironmentConfig
: type args : EnvironmentConfig
: type pip : str
: rtype : str
: rtype : str
"""
"""
stdout , _ = run_command ( args , [ ' pip ' , ' list ' ] , capture = True , always = True )
stdout , _ = run_command ( args , [ pip , ' list ' ] , capture = True )
return stdout
return stdout
@ -244,14 +244,14 @@ def generate_egg_info(args):
if os . path . isdir ( ' lib/ansible.egg-info ' ) :
if os . path . isdir ( ' lib/ansible.egg-info ' ) :
return
return
run_command ( args , [ ' python ' , ' setup.py ' , ' egg_info ' ] , capture = args . verbosity < 3 )
run_command ( args , [ ' python %s ' % args . python_version , ' setup.py ' , ' egg_info ' ] , capture = args . verbosity < 3 )
def generate_pip_install ( command, package s= None , extra s= None ) :
def generate_pip_install ( pip, command, package s= None ) :
"""
"""
: type pip : str
: type command : str
: type command : str
: type packages : list [ str ] | None
: type packages : list [ str ] | None
: type extras : list [ str ] | None
: rtype : list [ str ] | None
: rtype : list [ str ] | None
"""
"""
constraints = ' test/runner/requirements/constraints.txt '
constraints = ' test/runner/requirements/constraints.txt '
@ -259,15 +259,8 @@ def generate_pip_install(command, packages=None, extras=None):
options = [ ]
options = [ ]
requirements_list = [ requirements ]
if os . path . exists ( requirements ) and os . path . getsize ( requirements ) :
options + = [ ' -r ' , requirements ]
if extras :
for extra in extras :
requirements_list . append ( ' test/runner/requirements/ %s . %s .txt ' % ( command , extra ) )
for requirements in requirements_list :
if os . path . exists ( requirements ) and os . path . getsize ( requirements ) :
options + = [ ' -r ' , requirements ]
if packages :
if packages :
options + = packages
options + = packages
@ -275,7 +268,7 @@ def generate_pip_install(command, packages=None, extras=None):
if not options :
if not options :
return None
return None
return [ ' pip ' , ' install ' , ' --disable-pip-version-check ' , ' -c ' , constraints ] + options
return [ pip , ' install ' , ' --disable-pip-version-check ' , ' -c ' , constraints ] + options
def command_shell ( args ) :
def command_shell ( args ) :
@ -323,31 +316,24 @@ def command_network_integration(args):
)
)
all_targets = tuple ( walk_network_integration_targets ( include_hidden = True ) )
all_targets = tuple ( walk_network_integration_targets ( include_hidden = True ) )
internal_targets = command_integration_filter ( args , all_targets )
internal_targets = command_integration_filter ( args , all_targets , init_callback = network_init )
platform_targets = set ( a for t in internal_targets for a in t . aliases if a . startswith ( ' network/ ' ) )
if args . platform :
if args . platform :
configs = dict ( ( config [ ' platform_version ' ] , config ) for config in args . metadata . instance_config )
instances = [ ] # type: list [lib.thread.WrappedThread]
instances = [ ] # type: list [lib.thread.WrappedThread]
# generate an ssh key (if needed) up front once, instead of for each instance
SshKey ( args )
for platform_version in args . platform :
for platform_version in args . platform :
platform , version = platform_version . split ( ' / ' , 1 )
platform , version = platform_version . split ( ' / ' , 1 )
platform_target = ' network/ %s / ' % platform
config = configs . get ( platform_version )
if platform_target not in platform_targets and ' network/basics/ ' not in platform_targets :
if not config :
display . warning ( ' Skipping " %s " because selected tests do not target the " %s " platform. ' % (
platform_version , platform ) )
continue
continue
instance = lib . thread . WrappedThread ( functools . partial ( network_run , args , platform , version ))
instance = lib . thread . WrappedThread ( functools . partial ( network_run , args , platform , version , config ))
instance . daemon = True
instance . daemon = True
instance . start ( )
instance . start ( )
instances . append ( instance )
instances . append ( instance )
install_command_requirements ( args )
while any ( instance . is_alive ( ) for instance in instances ) :
while any ( instance . is_alive ( ) for instance in instances ) :
time . sleep ( 1 )
time . sleep ( 1 )
@ -359,22 +345,71 @@ def command_network_integration(args):
if not args . explain :
if not args . explain :
with open ( filename , ' w ' ) as inventory_fd :
with open ( filename , ' w ' ) as inventory_fd :
inventory_fd . write ( inventory )
inventory_fd . write ( inventory )
else :
install_command_requirements ( args )
command_integration_filtered ( args , internal_targets , all_targets )
command_integration_filtered ( args , internal_targets , all_targets )
def network_run ( args , platform , version ) :
def network_init ( args , internal_targets ) :
"""
: type args : NetworkIntegrationConfig
: type internal_targets : tuple [ IntegrationTarget ]
"""
if not args . platform :
return
if args . metadata . instance_config is not None :
return
platform_targets = set ( a for t in internal_targets for a in t . aliases if a . startswith ( ' network/ ' ) )
instances = [ ] # type: list [lib.thread.WrappedThread]
# generate an ssh key (if needed) up front once, instead of for each instance
SshKey ( args )
for platform_version in args . platform :
platform , version = platform_version . split ( ' / ' , 1 )
platform_target = ' network/ %s / ' % platform
if platform_target not in platform_targets and ' network/basics/ ' not in platform_targets :
display . warning ( ' Skipping " %s " because selected tests do not target the " %s " platform. ' % (
platform_version , platform ) )
continue
instance = lib . thread . WrappedThread ( functools . partial ( network_start , args , platform , version ) )
instance . daemon = True
instance . start ( )
instances . append ( instance )
while any ( instance . is_alive ( ) for instance in instances ) :
time . sleep ( 1 )
args . metadata . instance_config = [ instance . wait_for_result ( ) for instance in instances ]
def network_start ( args , platform , version ) :
"""
"""
: type args : NetworkIntegrationConfig
: type args : NetworkIntegrationConfig
: type platform : str
: type platform : str
: type version : str
: type version : str
: rtype : AnsibleCoreCI
: rtype : AnsibleCoreCI
"""
"""
core_ci = AnsibleCoreCI ( args , platform , version , stage = args . remote_stage )
core_ci = AnsibleCoreCI ( args , platform , version , stage = args . remote_stage )
core_ci . start ( )
core_ci . start ( )
return core_ci . save ( )
def network_run ( args , platform , version , config ) :
"""
: type args : NetworkIntegrationConfig
: type platform : str
: type version : str
: type config : dict [ str , str ]
: rtype : AnsibleCoreCI
"""
core_ci = AnsibleCoreCI ( args , platform , version , stage = args . remote_stage , load = False )
core_ci . load ( config )
core_ci . wait ( )
core_ci . wait ( )
manage = ManageNetworkCI ( core_ci )
manage = ManageNetworkCI ( core_ci )
@ -431,19 +466,20 @@ def command_windows_integration(args):
raise ApplicationError ( ' Use the --windows option or provide an inventory file (see %s .template). ' % filename )
raise ApplicationError ( ' Use the --windows option or provide an inventory file (see %s .template). ' % filename )
all_targets = tuple ( walk_windows_integration_targets ( include_hidden = True ) )
all_targets = tuple ( walk_windows_integration_targets ( include_hidden = True ) )
internal_targets = command_integration_filter ( args , all_targets )
internal_targets = command_integration_filter ( args , all_targets , init_callback = windows_init )
if args . windows :
if args . windows :
configs = dict ( ( config [ ' platform_version ' ] , config ) for config in args . metadata . instance_config )
instances = [ ] # type: list [lib.thread.WrappedThread]
instances = [ ] # type: list [lib.thread.WrappedThread]
for version in args . windows :
for version in args . windows :
instance = lib . thread . WrappedThread ( functools . partial ( windows_run , args , version ) )
config = configs [ ' windows/ %s ' % version ]
instance = lib . thread . WrappedThread ( functools . partial ( windows_run , args , version , config ) )
instance . daemon = True
instance . daemon = True
instance . start ( )
instance . start ( )
instances . append ( instance )
instances . append ( instance )
install_command_requirements ( args )
while any ( instance . is_alive ( ) for instance in instances ) :
while any ( instance . is_alive ( ) for instance in instances ) :
time . sleep ( 1 )
time . sleep ( 1 )
@ -455,16 +491,36 @@ def command_windows_integration(args):
if not args . explain :
if not args . explain :
with open ( filename , ' w ' ) as inventory_fd :
with open ( filename , ' w ' ) as inventory_fd :
inventory_fd . write ( inventory )
inventory_fd . write ( inventory )
else :
install_command_requirements ( args )
try :
command_integration_filtered ( args , internal_targets , all_targets )
command_integration_filtered ( args , internal_targets , all_targets )
finally :
pass
def windows_init ( args , internal_targets ) : # pylint: disable=locally-disabled, unused-argument
"""
: type args : WindowsIntegrationConfig
: type internal_targets : tuple [ IntegrationTarget ]
"""
if not args . windows :
return
if args . metadata . instance_config is not None :
return
instances = [ ] # type: list [lib.thread.WrappedThread]
for version in args . windows :
instance = lib . thread . WrappedThread ( functools . partial ( windows_start , args , version ) )
instance . daemon = True
instance . start ( )
instances . append ( instance )
while any ( instance . is_alive ( ) for instance in instances ) :
time . sleep ( 1 )
def windows_run ( args , version ) :
args . metadata . instance_config = [ instance . wait_for_result ( ) for instance in instances ]
def windows_start ( args , version ) :
"""
"""
: type args : WindowsIntegrationConfig
: type args : WindowsIntegrationConfig
: type version : str
: type version : str
@ -472,6 +528,19 @@ def windows_run(args, version):
"""
"""
core_ci = AnsibleCoreCI ( args , ' windows ' , version , stage = args . remote_stage )
core_ci = AnsibleCoreCI ( args , ' windows ' , version , stage = args . remote_stage )
core_ci . start ( )
core_ci . start ( )
return core_ci . save ( )
def windows_run ( args , version , config ) :
"""
: type args : WindowsIntegrationConfig
: type version : str
: type config : dict [ str , str ]
: rtype : AnsibleCoreCI
"""
core_ci = AnsibleCoreCI ( args , ' windows ' , version , stage = args . remote_stage , load = False )
core_ci . load ( config )
core_ci . wait ( )
core_ci . wait ( )
manage = ManageWindowsCI ( core_ci )
manage = ManageWindowsCI ( core_ci )
@ -525,10 +594,11 @@ def windows_inventory(remotes):
return inventory
return inventory
def command_integration_filter ( args , targets ):
def command_integration_filter ( args , targets , init_callback = None ):
"""
"""
: type args : IntegrationConfig
: type args : IntegrationConfig
: type targets : collections . Iterable [ IntegrationTarget ]
: type targets : collections . Iterable [ IntegrationTarget ]
: type init_callback : ( IntegrationConfig , tuple [ IntegrationTarget ] ) - > None
: rtype : tuple [ IntegrationTarget ]
: rtype : tuple [ IntegrationTarget ]
"""
"""
targets = tuple ( target for target in targets if ' hidden/ ' not in target . aliases )
targets = tuple ( target for target in targets if ' hidden/ ' not in target . aliases )
@ -551,6 +621,9 @@ def command_integration_filter(args, targets):
if args . start_at and not any ( t . name == args . start_at for t in internal_targets ) :
if args . start_at and not any ( t . name == args . start_at for t in internal_targets ) :
raise ApplicationError ( ' Start at target matches nothing: %s ' % args . start_at )
raise ApplicationError ( ' Start at target matches nothing: %s ' % args . start_at )
if init_callback :
init_callback ( args , internal_targets )
cloud_init ( args , internal_targets )
cloud_init ( args , internal_targets )
if args . delegate :
if args . delegate :
@ -880,7 +953,7 @@ def command_units(args):
for version in SUPPORTED_PYTHON_VERSIONS :
for version in SUPPORTED_PYTHON_VERSIONS :
# run all versions unless version given, in which case run only that version
# run all versions unless version given, in which case run only that version
if args . python and version != args . python :
if args . python and version != args . python _version :
continue
continue
env = ansible_environment ( args )
env = ansible_environment ( args )
@ -940,7 +1013,7 @@ def command_compile(args):
for version in COMPILE_PYTHON_VERSIONS :
for version in COMPILE_PYTHON_VERSIONS :
# run all versions unless version given, in which case run only that version
# run all versions unless version given, in which case run only that version
if args . python and version != args . python :
if args . python and version != args . python _version :
continue
continue
display . info ( ' Compile with Python %s ' % version )
display . info ( ' Compile with Python %s ' % version )
@ -1027,104 +1100,6 @@ def compile_version(args, python_version, include, exclude):
return TestSuccess ( command , test , python_version = python_version )
return TestSuccess ( command , test , python_version = python_version )
def intercept_command ( args , cmd , target_name , capture = False , env = None , data = None , cwd = None , python_version = None , path = None ) :
"""
: type args : TestConfig
: type cmd : collections . Iterable [ str ]
: type target_name : str
: type capture : bool
: type env : dict [ str , str ] | None
: type data : str | None
: type cwd : str | None
: type python_version : str | None
: type path : str | None
: rtype : str | None , str | None
"""
if not env :
env = common_environment ( )
cmd = list ( cmd )
inject_path = get_coverage_path ( args )
config_path = os . path . join ( inject_path , ' injector.json ' )
version = python_version or args . python_version
interpreter = find_executable ( ' python %s ' % version , path = path )
coverage_file = os . path . abspath ( os . path . join ( inject_path , ' .. ' , ' output ' , ' %s = %s = %s = %s =coverage ' % (
args . command , target_name , args . coverage_label or ' local- %s ' % version , ' python- %s ' % version ) ) )
env [ ' PATH ' ] = inject_path + os . pathsep + env [ ' PATH ' ]
env [ ' ANSIBLE_TEST_PYTHON_VERSION ' ] = version
env [ ' ANSIBLE_TEST_PYTHON_INTERPRETER ' ] = interpreter
config = dict (
python_interpreter = interpreter ,
coverage_file = coverage_file if args . coverage else None ,
)
if not args . explain :
with open ( config_path , ' w ' ) as config_fd :
json . dump ( config , config_fd , indent = 4 , sort_keys = True )
return run_command ( args , cmd , capture = capture , env = env , data = data , cwd = cwd )
def get_coverage_path ( args ) :
"""
: type args : TestConfig
: rtype : str
"""
global coverage_path # pylint: disable=locally-disabled, global-statement, invalid-name
if coverage_path :
return os . path . join ( coverage_path , ' coverage ' )
prefix = ' ansible-test-coverage- '
tmp_dir = ' /tmp '
if args . explain :
return os . path . join ( tmp_dir , ' %s tmp ' % prefix , ' coverage ' )
src = os . path . abspath ( os . path . join ( os . getcwd ( ) , ' test/runner/injector/ ' ) )
coverage_path = tempfile . mkdtemp ( ' ' , prefix , dir = tmp_dir )
os . chmod ( coverage_path , stat . S_IRWXU | stat . S_IRGRP | stat . S_IXGRP | stat . S_IROTH | stat . S_IXOTH )
shutil . copytree ( src , os . path . join ( coverage_path , ' coverage ' ) )
shutil . copy ( ' .coveragerc ' , os . path . join ( coverage_path , ' coverage ' , ' .coveragerc ' ) )
for root , dir_names , file_names in os . walk ( coverage_path ) :
for name in dir_names + file_names :
os . chmod ( os . path . join ( root , name ) , stat . S_IRWXU | stat . S_IRGRP | stat . S_IXGRP | stat . S_IROTH | stat . S_IXOTH )
for directory in ' output ' , ' logs ' :
os . mkdir ( os . path . join ( coverage_path , directory ) )
os . chmod ( os . path . join ( coverage_path , directory ) , stat . S_IRWXU | stat . S_IRWXG | stat . S_IRWXO )
atexit . register ( cleanup_coverage_dir )
return os . path . join ( coverage_path , ' coverage ' )
def cleanup_coverage_dir ( ) :
""" Copy over coverage data from temporary directory and purge temporary directory. """
output_dir = os . path . join ( coverage_path , ' output ' )
for filename in os . listdir ( output_dir ) :
src = os . path . join ( output_dir , filename )
dst = os . path . join ( os . getcwd ( ) , ' test ' , ' results ' , ' coverage ' )
shutil . copy ( src , dst )
logs_dir = os . path . join ( coverage_path , ' logs ' )
for filename in os . listdir ( logs_dir ) :
random_suffix = ' ' . join ( random . choice ( string . ascii_letters + string . digits ) for _ in range ( 8 ) )
new_name = ' %s . %s .log ' % ( os . path . splitext ( os . path . basename ( filename ) ) [ 0 ] , random_suffix )
src = os . path . join ( logs_dir , filename )
dst = os . path . join ( os . getcwd ( ) , ' test ' , ' results ' , ' logs ' , new_name )
shutil . copy ( src , dst )
shutil . rmtree ( coverage_path )
def get_changes_filter ( args ) :
def get_changes_filter ( args ) :
"""
"""
: type args : TestConfig
: type args : TestConfig
@ -1306,12 +1281,16 @@ def get_integration_local_filter(args, targets):
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
if args . python_version . startswith ( ' 3 ' ) :
if args . python_version . startswith ( ' 3 ' ) :
skip = ' skip/python3/ '
python_version = 3
skipped = [ target . name for target in targets if skip in target . aliases ]
else :
if skipped :
python_version = 2
exclude . append ( skip )
display . warning ( ' Excluding tests marked " %s " which are not yet supported on python 3: %s '
skip = ' skip/python %d / ' % python_version
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
skipped = [ target . name for target in targets if skip in target . aliases ]
if skipped :
exclude . append ( skip )
display . warning ( ' Excluding tests marked " %s " which are not supported on python %d : %s '
% ( skip . rstrip ( ' / ' ) , python_version , ' , ' . join ( skipped ) ) )
return exclude
return exclude
@ -1332,13 +1311,26 @@ def get_integration_docker_filter(args, targets):
display . warning ( ' Excluding tests marked " %s " which require --docker-privileged to run under docker: %s '
display . warning ( ' Excluding tests marked " %s " which require --docker-privileged to run under docker: %s '
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
python_version = 2 # images are expected to default to python 2 unless otherwise specified
if args . docker . endswith ( ' py3 ' ) :
if args . docker . endswith ( ' py3 ' ) :
skip = ' skip/python3/ '
python_version = 3 # docker images ending in 'py3' are expected to default to python 3
skipped = [ target . name for target in targets if skip in target . aliases ]
if skipped :
if args . docker . endswith ( ' :default ' ) :
exclude . append ( skip )
python_version = 3 # docker images tagged 'default' are expected to default to python 3
display . warning ( ' Excluding tests marked " %s " which are not yet supported on python 3: %s '
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
if args . python : # specifying a numeric --python option overrides the default python
if args . python . startswith ( ' 3 ' ) :
python_version = 3
elif args . python . startswith ( ' 2 ' ) :
python_version = 2
skip = ' skip/python %d / ' % python_version
skipped = [ target . name for target in targets if skip in target . aliases ]
if skipped :
exclude . append ( skip )
display . warning ( ' Excluding tests marked " %s " which are not supported on python %d : %s '
% ( skip . rstrip ( ' / ' ) , python_version , ' , ' . join ( skipped ) ) )
return exclude
return exclude
@ -1359,9 +1351,18 @@ def get_integration_remote_filter(args, targets):
skipped = [ target . name for target in targets if skip in target . aliases ]
skipped = [ target . name for target in targets if skip in target . aliases ]
if skipped :
if skipped :
exclude . append ( skip )
exclude . append ( skip )
display . warning ( ' Excluding tests marked " %s " which are not yet supported on %s : %s '
display . warning ( ' Excluding tests marked " %s " which are not supported on %s : %s '
% ( skip . rstrip ( ' / ' ) , platform , ' , ' . join ( skipped ) ) )
% ( skip . rstrip ( ' / ' ) , platform , ' , ' . join ( skipped ) ) )
python_version = 2 # remotes are expected to default to python 2
skip = ' skip/python %d / ' % python_version
skipped = [ target . name for target in targets if skip in target . aliases ]
if skipped :
exclude . append ( skip )
display . warning ( ' Excluding tests marked " %s " which are not supported on python %d : %s '
% ( skip . rstrip ( ' / ' ) , python_version , ' , ' . join ( skipped ) ) )
return exclude
return exclude