"""Runway context."""from__future__importannotationsimportloggingimportsysfromtypingimportTYPE_CHECKING,Any,castfrom..compatimportcached_propertyfrom..core.componentsimportDeployEnvironmentfrom._baseimportBaseContextifTYPE_CHECKING:frompathlibimportPathfrom.._loggingimportPrefixAdaptor,RunwayLoggerfrom..core.type_defsimportRunwayActionTypeDefLOGGER=cast("RunwayLogger",logging.getLogger(__name__))defstr2bool(v:str)->bool:"""Return boolean value of string."""returnv.lower()in("yes","true","t","1","on","y")
[docs]classRunwayContext(BaseContext):"""Runway context object."""changeset_results:dict[str,str]"""Mapping of stack FQN to changeset ID for retained changesets."""command:RunwayActionTypeDef|None"""Runway command/action being run."""create_changeset:bool"""Whether to retain CloudFormation changesets instead of deleting them."""output_format:str"""Output format for changeset information (text or json)."""stack_names:list[str]"""CFNgin stack names to target. If empty, all stacks are targeted."""
[docs]def__init__(self,*,command:RunwayActionTypeDef|None=None,create_changeset:bool=False,deploy_environment:DeployEnvironment|None=None,logger:PrefixAdaptor|RunwayLogger=LOGGER,output_format:str="text",stack_names:list[str]|None=None,work_dir:Path|None=None,**_:Any,)->None:"""Instantiate class. Args: command: Runway command/action being run. create_changeset: Whether to retain changesets instead of deleting. deploy_environment: The current deploy environment. logger: Custom logger. output_format: Output format for changeset info (text or json). stack_names: CFNgin stack names to target. If not provided, all stacks defined in the config will be targeted. work_dir: Working directory used by Runway. """super().__init__(deploy_environment=deploy_environmentorDeployEnvironment(),logger=logger,work_dir=work_dir,)self.changeset_results={}self.command=commandself.create_changeset=create_changesetself.output_format=output_formatself.stack_names=stack_namesor[]self._inject_profile_credentials()
@cached_propertydefno_color(self)->bool:"""Whether to explicitly disable color output. Primarily applies to IaC being wrapped by Runway. """colorize=self.env.vars.get("RUNWAY_COLORIZE")# explicitly enable/disabletry:ifisinstance(colorize,bool):# pyright: ignore[reportUnnecessaryIsInstance]# catch Falsereturnnotcolorizeifcolorizeandisinstance(colorize,str):# type: ignorereturnnotstr2bool(colorize)exceptValueError:pass# likely invalid RUNWAY_COLORIZE valuereturnnotsys.stdout.isatty()@cached_propertydefuse_concurrent(self)->bool:"""Whether to use concurrent.futures or not. Noninteractive is required for concurrent execution to prevent weird user-input behavior. Python 3 is required because backported futures has issues with ProcessPoolExecutor. """ifself.is_noninteractive:ifnotself.sys_info.os.is_posix:LOGGER.warning("parallel execution disabled; only POSIX systems are supported currently")returnFalsereturnTrueLOGGER.warning("parallel execution disabled; not running in CI mode")returnFalse
[docs]defcopy(self)->RunwayContext:"""Copy the contents of this object into a new instance."""returnself.__class__(command=self.command,create_changeset=self.create_changeset,deploy_environment=self.env.copy(),logger=self.logger,output_format=self.output_format,stack_names=self.stack_names.copy(),work_dir=self.work_dir,)
[docs]defecho_detected_environment(self)->None:"""Print a helper note about how the environment was determined."""self.env.log_name()