70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
import re
|
|
import streamlit as st
|
|
import pandas as pd
|
|
import numpy as np
|
|
from io import StringIO
|
|
import sys
|
|
from typing import TYPE_CHECKING
|
|
from mdcollections.base_types import MDPage
|
|
|
|
# if TYPE_CHECKING:
|
|
# from .markdown_server import MDServer
|
|
|
|
def execute_streamlit_code(code_block):
|
|
"""
|
|
Execute a streamlit code block and capture its output.
|
|
The code block should be valid Python code that uses streamlit.
|
|
"""
|
|
# Create string buffer to capture any print outputs
|
|
old_stdout = sys.stdout
|
|
redirected_output = StringIO()
|
|
sys.stdout = redirected_output
|
|
|
|
try:
|
|
# Execute the code block
|
|
# The code block can use st, pd, np which are already imported
|
|
exec(code_block, {
|
|
'st': st,
|
|
'pd': pd,
|
|
'np': np
|
|
})
|
|
|
|
# Get any printed output
|
|
printed_output = redirected_output.getvalue()
|
|
return True, printed_output
|
|
except Exception as e:
|
|
return False, f"Error: {str(e)}\n\nFailed code:\n{code_block}"
|
|
finally:
|
|
# Restore stdout
|
|
sys.stdout = old_stdout
|
|
|
|
|
|
def process_streamlit_blocks(page: MDPage) -> MDPage:
|
|
"""
|
|
Find and process ```py sl code blocks in markdown content.
|
|
Returns the modified content with executed streamlit code blocks replaced by their output.
|
|
"""
|
|
if not isinstance(page, MDPage):
|
|
raise TypeError("page must be a MDPage")
|
|
# if not hasattr(md_server, 'collections_manager'):
|
|
# raise TypeError("md_server must be an instance of MDServer")
|
|
|
|
def replace_code_block(match):
|
|
code = match.group(1).strip()
|
|
success, result = execute_streamlit_code(code)
|
|
|
|
if not success:
|
|
# If execution failed, return the error message
|
|
return f"```\n{result}\n```"
|
|
|
|
# If successful, return empty string - the streamlit components
|
|
# will be rendered but the code block itself won't be shown
|
|
return ""
|
|
|
|
# Process the code block
|
|
processed_content = re.sub(r"```py\s+sl\n(.*?)\n```", replace_code_block, page.content, flags=re.DOTALL)
|
|
|
|
page.content_ = processed_content
|
|
|
|
return page
|