Spaces:
Sleeping
Sleeping
| 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) | |
| def check_device_lib(): | |
| """Check if device.lib exists in the current directory.""" | |
| current_dir = os.getcwd() | |
| device_lib_path = os.path.join(current_dir, 'device.lib') | |
| if os.path.exists(device_lib_path): | |
| logger.info(f"Found device.lib in current directory: {device_lib_path}") | |
| return True | |
| logger.warning(f"device.lib not found in current directory: {current_dir}") | |
| return False | |
| def configure_skidl_libs(): | |
| """Configure SKiDL to use device.lib from the current directory.""" | |
| current_dir = os.getcwd() | |
| # Clear existing library search paths | |
| lib_search_paths.clear() | |
| # Assume lib_search_paths is a dict (newer SKiDL) | |
| lib_key = getattr(skidl, 'LIB_SPICE', 'spice') | |
| lib_search_paths[lib_key] = [current_dir] | |
| logger.info(f"Using dict-based lib_search_paths with key '{lib_key}' and {current_dir}") | |
| # Conditionally set default library if set_default_lib exists | |
| try: | |
| set_default_lib('Device') | |
| logger.info("Set default library to Device using set_default_lib") | |
| except NameError: | |
| logger.info("set_default_lib not available; relying on lib_search_paths for Device library") | |
| # Suppress KiCad warnings by setting dummy environment variables | |
| os.environ['KICAD_SYMBOL_DIR'] = current_dir | |
| os.environ['KICAD6_SYMBOL_DIR'] = current_dir | |
| os.environ['KICAD7_SYMBOL_DIR'] = current_dir | |
| os.environ['KICAD8_SYMBOL_DIR'] = current_dir | |
| logger.info("Set dummy KiCad environment variables to suppress warnings") | |
| 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.""" | |
| if not skidl_code.strip(): | |
| return "Error: Empty code provided", None | |
| reset() | |
| tmp_path = None | |
| try: | |
| configure_skidl_libs() | |
| if not check_device_lib(): | |
| return "Error: device.lib not found in the current directory. Please ensure it exists.", None | |
| try: | |
| compile(skidl_code, '<string>', 'exec') | |
| except SyntaxError as e: | |
| return f"Syntax Error: {e}", None | |
| with tempfile.NamedTemporaryFile(delete=False, suffix='.py') as tmp: | |
| tmp.write(skidl_code.encode('utf-8')) | |
| tmp_path = tmp.name | |
| namespace = {} | |
| exec(open(tmp_path).read(), namespace) | |
| netlist_str = generate_netlist() | |
| if not netlist_str.strip(): | |
| return "Error: No netlist generated", None | |
| 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: | |
| 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 `device.lib` is in the same directory as this script to resolve components like resistors, LEDs, etc. | |
| """ | |
| ) | |
| # Example code: 5 LEDs with resistors | |
| example_code = """ | |
| from skidl import * | |
| vcc = Vcc() | |
| gnd = Gnd() | |
| leds = [Part('Device', 'LED', value='LED') for _ in range(5)] | |
| resistors = [Part('Device', 'R', value='220') for _ in range(5)] | |
| for r, led in zip(resistors, leds): | |
| vcc & r & led & gnd | |
| """ | |
| 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() |