55
66from typing import Optional , List
77
8- from .Check import Check
8+ from .install_and_test import InstallAndTest
99from ci_tools .functions import (
1010 install_into_venv ,
1111 uninstall_from_venv ,
12- is_error_code_5_allowed ,
1312)
14- from ci_tools .scenario .generation import create_package_and_install , prepare_environment
15- from ci_tools .variables import discover_repo_root , in_ci , set_envvar_defaults
16- from ci_tools .environment_exclusions import is_check_enabled
13+ from ci_tools .scenario .generation import prepare_environment
14+ from ci_tools .variables import discover_repo_root , set_envvar_defaults
1715from ci_tools .parsing import get_config_setting
1816from ci_tools .logging import logger
1917
2018REPO_ROOT = discover_repo_root ()
2119
2220
23- class optional (Check ):
21+ class optional (InstallAndTest ):
2422 def __init__ (self ) -> None :
25- super ().__init__ ()
23+ super ().__init__ (package_type = "sdist" , proxy_url = "http://localhost:5004" , display_name = "optional" )
2624
2725 def register (
2826 self , subparsers : "argparse._SubParsersAction" , parent_parsers : Optional [List [argparse .ArgumentParser ]] = None
@@ -48,31 +46,29 @@ def run(self, args: argparse.Namespace) -> int:
4846 """Run the optional check command."""
4947 logger .info ("Running optional check..." )
5048
51- set_envvar_defaults ({"PROXY_URL" : "http://localhost:5004" })
49+ env_defaults = self .get_env_defaults ()
50+ if env_defaults :
51+ set_envvar_defaults (env_defaults )
52+
5253 targeted = self .get_targeted_directories (args )
54+ if not targeted :
55+ logger .warning ("No target packages discovered for optional check." )
56+ return 0
5357
5458 results : List [int ] = []
5559
5660 for parsed in targeted :
5761 package_dir = parsed .folder
5862 package_name = parsed .name
5963 executable , staging_directory = self .get_executable (args .isolate , args .command , sys .executable , package_dir )
60- logger .info (f"Processing { package_name } for optional check" )
61-
62- if in_ci ():
63- if not is_check_enabled (package_dir , "optional" , False ):
64- logger .info (f"Package { package_name } opts-out of optional check." )
65- continue
66-
67- try :
68- self .install_dev_reqs (executable , args , package_dir )
69- except CalledProcessError as exc :
70- logger .error (f"Failed to install dependencies for { package_name } : { exc } " )
71- results .append (exc .returncode )
72- continue
64+ logger .info (f"Processing { package_name } using interpreter { executable } " )
7365
7466 try :
75- self .prepare_and_test_optional (package_name , package_dir , staging_directory , args .optional )
67+ result = self .prepare_and_test_optional (
68+ package_name , package_dir , staging_directory , args .optional , args
69+ )
70+ if result != 0 :
71+ results .append (result )
7672 except Exception as e :
7773 logger .error (f"Optional check for package { package_name } failed with exception: { e } " )
7874 results .append (1 )
@@ -83,16 +79,19 @@ def run(self, args: argparse.Namespace) -> int:
8379 # TODO copying from generation.py, remove old code later
8480 # TODO remove pytest() function from ci_tools.functions as it was only used in the old version of this logic
8581 def prepare_and_test_optional (
86- self , package_name : str , package_dir : str , temp_dir : str , target_env_name : str
87- ) -> None :
82+ self , package_name : str , package_dir : str , temp_dir : str , target_env_name : str , args : argparse . Namespace
83+ ) -> int :
8884 """
8985 Prepare and test the optional environment for the given package.
9086 """
9187 optional_configs = get_config_setting (package_dir , "optional" )
9288
89+ if not isinstance (optional_configs , list ):
90+ optional_configs = []
91+
9392 if len (optional_configs ) == 0 :
9493 logger .info (f"No optional environments detected in pyproject.toml within { package_dir } ." )
95- exit ( 0 )
94+ return 0
9695
9796 config_results = []
9897
@@ -109,26 +108,18 @@ def prepare_and_test_optional(
109108
110109 environment_exe = prepare_environment (package_dir , temp_dir , env_name )
111110
112- create_package_and_install (
113- distribution_directory = temp_dir ,
114- target_setup = package_dir ,
115- skip_install = False ,
116- cache_dir = None ,
117- work_dir = temp_dir ,
118- force_create = False ,
119- package_type = "sdist" ,
120- pre_download_disabled = False ,
121- python_executable = environment_exe ,
122- )
123- dev_reqs = os .path .join (package_dir , "dev_requirements.txt" )
124- test_tools = os .path .join (REPO_ROOT , "eng" , "test_tools.txt" )
125-
126- # install the dev requirements and test_tools requirements files to ensure tests can run
111+ # install package and testing requirements
127112 try :
128- install_into_venv (environment_exe , ["-r" , dev_reqs , "-r" , test_tools ], package_dir )
113+ install_result = self .install_all_requiremenmts (
114+ environment_exe , temp_dir , package_name , package_dir , args
115+ )
116+ if install_result != 0 :
117+ logger .error (f"Failed to install base requirements for { package_name } in optional env { env_name } ." )
118+ config_results .append (False )
119+ break
129120 except CalledProcessError as exc :
130121 logger .error (
131- f"Unable to complete installation of dev_requirements.txt and/or test_tools.txt for { package_name } , check command output above. "
122+ f"Failed to install base requirements for { package_name } in optional env { env_name } : { exc } "
132123 )
133124 config_results .append (False )
134125 break
@@ -181,30 +172,16 @@ def prepare_and_test_optional(
181172
182173 logger .info (f"Invoking tests for package { package_name } and optional environment { env_name } " )
183174
184- pytest_command = ["-m" , "pytest" , * pytest_args ]
185- pytest_result = self .run_venv_command (
186- environment_exe , pytest_command , cwd = package_dir , immediately_dump = True
187- )
188-
189- if pytest_result .returncode != 0 :
190- if pytest_result .returncode == 5 and is_error_code_5_allowed (package_dir , package_name ):
191- logger .info (
192- "pytest exited with code 5 for %s, which is allowed for management or opt-out packages." ,
193- package_name ,
194- )
195- # Align with tox: skip coverage when tests are skipped entirely
196- continue
197- logger .error (
198- f"pytest failed for { package_name } and optional environment { env_name } with exit code { pytest_result .returncode } ."
175+ try :
176+ pytest_result = self .run_pytest (
177+ environment_exe , temp_dir , package_dir , package_name , pytest_args , cwd = package_dir
199178 )
179+ config_results .append (True if pytest_result == 0 else False )
180+ except CalledProcessError as exc :
200181 config_results .append (False )
201- else :
202- logger .info (f"pytest succeeded for { package_name } and optional environment { env_name } ." )
203- config_results .append (True )
204182
205183 if all (config_results ):
206184 logger .info (f"All optional environment(s) for { package_name } completed successfully." )
207- exit (0 )
208185 else :
209186 for i , config in enumerate (optional_configs ):
210187 if i >= len (config_results ):
@@ -214,4 +191,5 @@ def prepare_and_test_optional(
214191 logger .error (
215192 f"Optional environment { config_name } for { package_name } completed with non-zero exit-code. Check test results above."
216193 )
217- exit (1 )
194+ return 1
195+ return 0
0 commit comments