Skip to content

Interactive console in solara web interface. #2683

@Sahil-Chhoker

Description

@Sahil-Chhoker

This feature idea originates from discussions on PR #2674 and PR #2176. After setting up an environment for Python code execution in the Solara GUI (PR #2674), the idea of turning it into a more console-like experience was proposed. I decided to take a step back and create a minimal prototype to explore its potential. My plan is to refine the backend for code execution once the Solara GUI is fully developed. However, due to my limited knowledge of the Solara web framework, I’m opening this issue to gather ideas and collaborate on making this feature possible.

Current Implementation:

import solara
import sys
import code
import io


# Backend console stuff
class Interpreter(code.InteractiveInterpreter):
    def __init__(self):
        super().__init__()
        self.output_buffer = io.StringIO()

    def run_code(self, command):
        sys.stdout = self.output_buffer
        sys.stderr = self.output_buffer
        try:
            self.runsource(command)
            output = self.output_buffer.getvalue()
            return output if output else "Command executed successfully."
        except SyntaxError as e:
            return f"SyntaxError: {str(e).split(')')[-1].strip()}"
        except Exception as e:
            return f"{type(e).__name__}: {str(e)}"
        finally:
            sys.stdout = sys.__stdout__
            sys.stderr = sys.__stderr__
            self.output_buffer.truncate(0)
            self.output_buffer.seek(0)


interpreter = Interpreter()

# history list to replicate the console
history = []


def execute_code(input_text, set_input_text):
    if input_text.strip():
        output = interpreter.run_code(input_text)
        # error cleanup
        if isinstance(output, str) and "Traceback" in output:
            error_lines = output.strip().splitlines()
            for line in reversed(error_lines):
                if ": " in line:
                    output = line.strip()
                    break
        history.append((f">>> {input_text}", output))
        set_input_text("")


def clear_console():
    history.clear()


@solara.component
def Page():
    input_text, set_input_text = solara.use_state("")

    solara.Markdown(
        """
    # Python Console
    """
    )

    for cmd, result in history:
        solara.Markdown( # random styling + looks ugly 
            f"""
        <pre style="background-color: #f9f9f9; border: 1px solid #ddd; padding: 10px; border-radius: 1px; margin: 1px 0; font-family: 'Courier New', monospace; font-size: 14px;">
        ```python
        {cmd}
        ```
        {result}
        </pre>
        """
        )

    solara.InputText(
        value=input_text,
        label=">>>",
        continuous_update=True,
        on_value=set_input_text,
    )

    # For styling the input text
    solara.Style("""
    .v-text-field__slot {
        font-family: monospace !important;
    }
    """)

    solara.Button("Run", on_click=lambda: execute_code(input_text, set_input_text))
    solara.Button("Clear", on_click=clear_console)


Page()

Some features I am struggling to implement:

  1. Keyboard Enter -> Enter on app. ✔️
  2. Ctrl + L -> Console cleanup.
  3. Make the GUI look like a proper python console. ✔️

Features I am hoping to implement:

  1. Using _SecureCodeValidator from Feat: Added command center #2674 for validation of code executed in the console(if it gets a pass).
  2. Adding a variable explorer as suggested in this comment.

These features are open for discussion and feedback. I would greatly appreciate any new ideas or suggestions you may have!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions