<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def execute_shell(self, shell=None, parent_environ=None, rcfile=None, norc=False, stdin=False, command=None, quiet=False, block=None, actions_callback=None, post_actions_callback=None, context_filepath=None, start_new_session=False, detached=False, pre_command=None, **Popen_args):
 """Spawn a possibly-interactive shell. Args: shell: Shell type, for eg 'bash'. If None, the current shell type is used. parent_environ: Environment to run the shell process in, if None then the current environment is used. rcfile: Specify a file to source instead of shell startup files. norc: If True, skip shell startup files, if possible. stdin: If True, read commands from stdin, in a non-interactive shell. command: If not None, execute this command in a non-interactive shell. If an empty string or list, don't run a command, but don't open an interactive shell either. Can be a list of args. quiet: If True, skip the welcome message in interactive shells. block: If True, block until the shell is terminated. If False, return immediately. If None, will default to blocking if the shell is interactive. actions_callback: Callback with signature (RexExecutor). This lets the user append custom actions to the context, such as setting extra environment variables. Callback is run prior to context Rex execution. post_actions_callback: Callback with signature (RexExecutor). This lets the user append custom actions to the context, such as setting extra environment variables. Callback is run after context Rex execution. context_filepath: If provided, the context file will be written here, rather than to the default location (which is in a tempdir). If you use this arg, you are responsible for cleaning up the file. start_new_session: If True, change the process group of the target process. Note that this may override the Popen_args keyword 'preexec_fn'. detached: If True, open a separate terminal. Note that this may override the `pre_command` argument. pre_command: Command to inject before the shell command itself. This is for internal use. Popen_args: args to pass to the shell process object constructor. Returns: If blocking: A 3-tuple of (returncode, stdout, stderr); If non-blocking - A subprocess.Popen object for the shell process. """

        sh = create_shell(shell)

        if hasattr(command, "__iter__"):
            command = sh.join(command)

        # start a new session if specified
        if start_new_session:
            Popen_args.update(config.new_session_popen_args)

        # open a separate terminal if specified
        if detached:
            term_cmd = config.terminal_emulator_command
            if term_cmd:
                pre_command = term_cmd.strip().split()

        # block if the shell is likely to be interactive
        if block is None:
            block = not (command or stdin)

        # context and rxt files. If running detached, don't cleanup files, because
        # rez-env returns too early and deletes the tmp files before the detached
        # process can use them
        tmpdir = self.tmpdir_manager.mkdtemp(cleanup=not detached)

        if self.load_path and os.path.isfile(self.load_path):
            rxt_file = self.load_path
        else:
            rxt_file = os.path.join(tmpdir, "context.rxt")
            self.save(rxt_file)

        context_file = context_filepath or \
            os.path.join(tmpdir, "context.%s" % sh.file_extension())

        # interpret this context and write out the native context file
        executor = self._create_executor(sh, parent_environ)
        executor.env.REZ_RXT_FILE = rxt_file
        executor.env.REZ_CONTEXT_FILE = context_file

        if actions_callback:
            actions_callback(executor)

        self._execute(executor)

        if post_actions_callback:
            post_actions_callback(executor)

        context_code = executor.get_output()
        with open(context_file, 'w') as f:
            f.write(context_code)

        quiet = quiet or \
            (RezToolsVisibility[config.rez_tools_visibility] == RezToolsVisibility.never)

        # spawn the shell subprocess
        p = sh.spawn_shell(context_file,
                           tmpdir,
                           rcfile=rcfile,
                           norc=norc,
                           stdin=stdin,
                           command=command,
                           env=parent_environ,
                           quiet=quiet,
                           pre_command=pre_command,
                           **Popen_args)
        if block:
            stdout, stderr = p.communicate()
            return p.returncode, stdout, stderr
        else:
            return p