Skidl / app.py
Arrcttacsrks's picture
Update app.py
6cb9bde verified
raw
history blame
5 kB
import gradio as gr
from skidl import *
import tempfile
import os
import time
import sys
import logging
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Check for required dependencies
try:
import gradio
import skidl
except ImportError as e:
print(f"Missing dependency: {e}")
print("Please install requirements: pip install gradio skidl")
sys.exit(1)
# Check KiCad symbol directory environment variables
def check_kicad_env():
"""Check if KiCad symbol directory environment variables are set."""
kicad_vars = [
'KICAD_SYMBOL_DIR',
'KICAD6_SYMBOL_DIR',
'KICAD7_SYMBOL_DIR',
'KICAD8_SYMBOL_DIR'
]
missing = [var for var in kicad_vars if not os.environ.get(var)]
if missing:
logger.warning(
f"Missing KiCad environment variables: {', '.join(missing)}. "
"Set these to access default KiCad symbol libraries."
)
return False
return True
# Set default symbol library path if not set
def set_default_symbol_lib():
"""Set a fallback symbol library path if environment variables are missing."""
if not check_kicad_env():
# Use a generic library or custom path (modify as needed)
default_lib_path = os.path.expanduser("~/kicad_symbols") # Example path
if os.path.exists(default_lib_path):
os.environ['KICAD_SYMBOL_DIR'] = default_lib_path
lib_search_paths.append(default_lib_path)
logger.info(f"Set default symbol library path: {default_lib_path}")
else:
logger.warning(
f"Default symbol library path {default_lib_path} not found. "
"Parts may not be resolved without valid libraries."
)
def cleanup_old_files():
"""Clean up temporary files older than 1 hour."""
temp_dir = tempfile.gettempdir()
for f in os.listdir(temp_dir):
if f.endswith('.net') and os.path.getmtime(os.path.join(temp_dir, f)) < time.time() - 3600:
try:
os.remove(os.path.join(temp_dir, f))
except OSError:
pass
def generate_circuit(skidl_code):
"""Generate circuit netlist from SKiDL code."""
# Input validation
if not skidl_code.strip():
return "Error: Empty code provided", None
reset() # Reset SKiDL state
tmp_path = None
try:
# Set default symbol library if needed
set_default_symbol_lib()
# Validate code syntax
try:
compile(skidl_code, '<string>', 'exec')
except SyntaxError as e:
return f"Syntax Error: {e}", None
# Save code to temporary file
with tempfile.NamedTemporaryFile(delete=False, suffix='.py') as tmp:
tmp.write(skidl_code.encode('utf-8'))
tmp_path = tmp.name
# Execute code
namespace = {}
exec(open(tmp_path).read(), namespace)
# Generate netlist
netlist_str = generate_netlist()
if not netlist_str.strip():
return "Error: No netlist generated", None
# Save netlist to temporary file
with tempfile.NamedTemporaryFile(delete=False, suffix='.net', mode='w') as out_file:
out_file.write(netlist_str)
netlist_file_path = out_file.name
return "Netlist generated successfully!", netlist_file_path
except SyntaxError as e:
return f"Syntax Error: {e}", None
except Exception as e:
return f"Error: {str(e)}", None
finally:
# Clean up temporary file
if tmp_path and os.path.exists(tmp_path):
try:
os.remove(tmp_path)
except OSError:
pass
# Gradio UI
with gr.Blocks() as demo:
gr.Markdown(
"""
# SKiDL Circuit Builder (No KiCad Needed)
**Note**: Ensure KiCad symbol libraries are accessible by setting `KICAD_SYMBOL_DIR` or other relevant environment variables.
"""
)
# Example code with explicit library (Device library for basic components)
example_code = """
from skidl import *
# Use Device library for basic components
lib_search_paths.append('.') # Ensure local libraries are searchable
set_default_lib('Device') # Use built-in Device library
vcc = Vcc()
gnd = Gnd()
r1 = Part('Device', 'R', value='1k') # Explicitly use Device library
c1 = Part('Device', 'C', value='1uF')
r1[1] & c1 & gnd
r1[2] & vcc
"""
skidl_input = gr.Textbox(
label="Enter SKiDL Code Here",
lines=20,
placeholder=example_code
)
output_message = gr.Textbox(label="Status / Error", interactive=False)
download_btn = gr.File(label="Download Netlist (.net)")
run_button = gr.Button("Build Circuit")
run_button.click(
fn=generate_circuit,
inputs=[skidl_input],
outputs=[output_message, download_btn]
)
if __name__ == "__main__":
cleanup_old_files()
demo.launch()