Source code in src/prefect/deployments/steps/utility.py
6263646566676869707172
classRunShellScriptResult(TypedDict):""" The result of a `run_shell_script` step. Attributes: stdout: The captured standard output of the script. stderr: The captured standard error of the script. """stdout:strstderr:str
asyncdefpip_install_requirements(directory:Optional[str]=None,requirements_file:str="requirements.txt",stream_output:bool=True,):""" Installs dependencies from a requirements.txt file. Args: requirements_file: The requirements.txt to use for installation. directory: The directory the requirements.txt file is in. Defaults to the current working directory. stream_output: Whether to stream the output from pip install should be streamed to the console Returns: A dictionary with the keys `stdout` and `stderr` containing the output the `pip install` command Raises: subprocess.CalledProcessError: if the pip install command fails for any reason Example: ```yaml pull: - prefect.deployments.steps.git_clone: id: clone-step repository: https://github.com/org/repo.git - prefect.deployments.steps.pip_install_requirements: directory: {{ clone-step.directory }} requirements_file: requirements.txt stream_output: False ``` """stdout_sink=io.StringIO()stderr_sink=io.StringIO()asyncwithopen_process([get_sys_executable(),"-m","pip","install","-r",requirements_file],stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd=directory,)asprocess:await_stream_capture_process_output(process,stdout_sink=stdout_sink,stderr_sink=stderr_sink,stream_output=stream_output,)awaitprocess.wait()ifprocess.returncode!=0:raiseRuntimeError(f"pip_install_requirements failed with error code {process.returncode}:"f" {stderr_sink.getvalue()}")return{"stdout":stdout_sink.getvalue().strip(),"stderr":stderr_sink.getvalue().strip(),}
asyncdefrun_shell_script(script:str,directory:Optional[str]=None,env:Optional[Dict[str,str]]=None,stream_output:bool=True,expand_env_vars:bool=False,)->RunShellScriptResult:""" Runs one or more shell commands in a subprocess. Returns the standard output and standard error of the script. Args: script: The script to run directory: The directory to run the script in. Defaults to the current working directory. env: A dictionary of environment variables to set for the script stream_output: Whether to stream the output of the script to stdout/stderr expand_env_vars: Whether to expand environment variables in the script before running it Returns: A dictionary with the keys `stdout` and `stderr` containing the output of the script Examples: Retrieve the short Git commit hash of the current repository to use as a Docker image tag: ```yaml build: - prefect.deployments.steps.run_shell_script: id: get-commit-hash script: git rev-parse --short HEAD stream_output: false - prefect_docker.deployments.steps.build_docker_image: requires: prefect-docker image_name: my-image image_tag: "{{ get-commit-hash.stdout }}" dockerfile: auto ``` Run a multi-line shell script: ```yaml build: - prefect.deployments.steps.run_shell_script: script: | echo "Hello" echo "World" ``` Run a shell script with environment variables: ```yaml build: - prefect.deployments.steps.run_shell_script: script: echo "Hello $NAME" env: NAME: World ``` Run a shell script with environment variables expanded from the current environment: ```yaml pull: - prefect.deployments.steps.run_shell_script: script: | echo "User: $USER" echo "Home Directory: $HOME" stream_output: true expand_env_vars: true ``` Run a shell script in a specific directory: ```yaml build: - prefect.deployments.steps.run_shell_script: script: echo "Hello" directory: /path/to/directory ``` Run a script stored in a file: ```yaml build: - prefect.deployments.steps.run_shell_script: script: "bash path/to/script.sh" ``` """current_env=os.environ.copy()current_env.update(envor{})commands=script.splitlines()stdout_sink=io.StringIO()stderr_sink=io.StringIO()forcommandincommands:ifexpand_env_vars:# Expand environment variables in command and provided environmentcommand=string.Template(command).safe_substitute(current_env)split_command=shlex.split(command,posix=sys.platform!="win32")ifnotsplit_command:continueasyncwithopen_process(split_command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd=directory,env=current_env,)asprocess:await_stream_capture_process_output(process,stdout_sink=stdout_sink,stderr_sink=stderr_sink,stream_output=stream_output,)awaitprocess.wait()ifprocess.returncode!=0:raiseRuntimeError(f"`run_shell_script` failed with error code {process.returncode}:"f" {stderr_sink.getvalue()}")return{"stdout":stdout_sink.getvalue().strip(),"stderr":stderr_sink.getvalue().strip(),}