kicad-sch-api 0.1.7__py3-none-any.whl → 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kicad_sch_api/__init__.py CHANGED
@@ -42,11 +42,12 @@ Advanced Usage:
42
42
  print(f"Found {len(issues)} validation issues")
43
43
  """
44
44
 
45
- __version__ = "0.0.2"
45
+ __version__ = "0.3.0"
46
46
  __author__ = "Circuit-Synth"
47
47
  __email__ = "info@circuit-synth.com"
48
48
 
49
49
  from .core.components import Component, ComponentCollection
50
+ from .core.config import KiCADConfig, config
50
51
 
51
52
  # Core imports for public API
52
53
  from .core.schematic import Schematic
@@ -54,7 +55,7 @@ from .library.cache import SymbolLibraryCache, get_symbol_cache
54
55
  from .utils.validation import ValidationError, ValidationIssue
55
56
 
56
57
  # Version info
57
- VERSION_INFO = (0, 0, 2)
58
+ VERSION_INFO = (0, 3, 0)
58
59
 
59
60
  # Public API
60
61
  __all__ = [
@@ -64,6 +65,9 @@ __all__ = [
64
65
  "ComponentCollection",
65
66
  "SymbolLibraryCache",
66
67
  "get_symbol_cache",
68
+ # Configuration
69
+ "KiCADConfig",
70
+ "config",
67
71
  # Exceptions
68
72
  "ValidationError",
69
73
  "ValidationIssue",
kicad_sch_api/cli.py CHANGED
@@ -2,216 +2,119 @@
2
2
  """
3
3
  KiCAD Schematic API - Command Line Interface
4
4
 
5
- Provides helpful commands for setup, testing, and usage of the MCP server.
5
+ Provides helpful commands for testing and usage of the library.
6
6
  """
7
7
 
8
- import sys
9
- import json
10
- import os
11
- import subprocess
12
8
  import argparse
9
+ import subprocess
10
+ import sys
13
11
  from pathlib import Path
14
- from typing import Dict, Any
15
-
16
- def get_claude_config_path() -> Path:
17
- """Get the Claude Code configuration file path for current platform."""
18
- if sys.platform == "darwin":
19
- return Path.home() / "Library/Application Support/Claude/claude_desktop_config.json"
20
- elif sys.platform == "win32":
21
- return Path(os.environ["APPDATA"]) / "Claude/claude_desktop_config.json"
22
- else: # Linux and others
23
- return Path.home() / ".config/Claude/claude_desktop_config.json"
24
-
25
- def setup_claude_code() -> bool:
26
- """Automatically configure Claude Code MCP settings."""
27
- print("🔧 Setting up Claude Code MCP configuration...")
28
-
29
- config_path = get_claude_config_path()
30
-
31
- # Create directory if it doesn't exist
32
- config_path.parent.mkdir(parents=True, exist_ok=True)
33
-
34
- # Backup existing config
35
- if config_path.exists():
36
- backup_path = config_path.with_suffix(f".backup.{config_path.stat().st_mtime:.0f}.json")
37
- backup_path.write_text(config_path.read_text())
38
- print(f"📁 Backed up existing config to: {backup_path}")
39
-
40
- # Read existing config or create new one
41
- if config_path.exists():
42
- with open(config_path) as f:
43
- config = json.load(f)
44
- else:
45
- config = {}
46
-
47
- # Ensure mcpServers section exists
48
- if "mcpServers" not in config:
49
- config["mcpServers"] = {}
50
-
51
- # Use direct Python command - this is more reliable than trying to find binary paths
52
- config["mcpServers"]["kicad-sch-api"] = {
53
- "command": sys.executable,
54
- "args": ["-m", "kicad_sch_api.mcp.server"],
55
- "env": {}
56
- }
57
-
58
- # Write configuration
59
- with open(config_path, 'w') as f:
60
- json.dump(config, f, indent=2)
61
-
62
- print(f"✅ Configuration written to: {config_path}")
63
- print("🔄 Please restart Claude Code to apply changes")
64
- return True
12
+
65
13
 
66
14
  def test_installation() -> bool:
67
- """Test that the MCP server is working correctly."""
68
- print("🧪 Testing KiCAD Schematic MCP Server...")
69
-
15
+ """Test that the library is working correctly."""
16
+ print("🧪 Testing KiCAD Schematic API Library...")
17
+
70
18
  try:
71
- # Test import
72
- from kicad_sch_api.mcp.server import main as mcp_main
73
- print("✅ MCP server module imports successfully")
74
-
75
- # Test component discovery
76
- from kicad_sch_api.discovery.search_index import get_search_index
77
- print("✅ Component discovery system available")
78
-
79
- # Test KiCAD library access
19
+ # Test basic import
20
+ import kicad_sch_api
21
+
22
+ version = getattr(kicad_sch_api, "__version__", "unknown")
23
+ print(f"✅ Library imports successfully: v{version}")
24
+
25
+ # Test core functionality
26
+ import kicad_sch_api as ksa
27
+
28
+ sch = ksa.create_schematic("test")
29
+ print("✅ Can create schematic")
30
+
31
+ # Test component addition
32
+ sch.components.add(lib_id="Device:R", reference="R1", value="10k", position=(100, 100))
33
+ print("✅ Can add components")
34
+
35
+ # Test library access
80
36
  from kicad_sch_api.library.cache import get_symbol_cache
37
+
81
38
  cache = get_symbol_cache()
82
39
  stats = cache.get_performance_stats()
83
- print(f"✅ Symbol cache initialized: {stats['total_symbols_cached']} symbols")
84
-
40
+ print(f"✅ Symbol cache available: {stats['total_symbols_cached']} symbols")
41
+
85
42
  print("🎉 All tests passed!")
86
43
  return True
87
-
44
+
88
45
  except Exception as e:
89
46
  print(f"❌ Test failed: {e}")
90
47
  return False
91
48
 
49
+
92
50
  def show_status() -> bool:
93
- """Show current installation and configuration status."""
94
- print("📊 KiCAD Schematic MCP Server Status")
51
+ """Show current installation status."""
52
+ print("📊 KiCAD Schematic API Library Status")
95
53
  print("=" * 40)
96
-
54
+
97
55
  # Check installation
98
56
  try:
99
57
  import kicad_sch_api
100
- version = getattr(kicad_sch_api, '__version__', 'unknown')
101
- print(f"✅ Package installed: v{version}")
58
+
59
+ version = getattr(kicad_sch_api, "__version__", "unknown")
60
+ print(f"✅ Library installed: v{version}")
102
61
  except ImportError:
103
- print("❌ Package not installed")
62
+ print("❌ Library not installed")
104
63
  return False
105
-
106
- # Check MCP command
107
- mcp_cmd_path = None
108
- try:
109
- result = subprocess.run(['kicad-sch-mcp', '--help'],
110
- capture_output=True, timeout=5)
111
- if result.returncode == 0:
112
- print("✅ MCP command available")
113
- mcp_cmd_path = "kicad-sch-mcp"
114
- else:
115
- print("⚠️ MCP command found but returns error")
116
- except (subprocess.TimeoutExpired, FileNotFoundError):
117
- # Try to find the command in common locations
118
- import sys
119
- python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
120
- possible_paths = [
121
- f"/Library/Frameworks/Python.framework/Versions/{python_version}/bin/kicad-sch-mcp",
122
- os.path.expanduser(f"~/Library/Python/{python_version}/bin/kicad-sch-mcp"),
123
- os.path.expanduser("~/.local/bin/kicad-sch-mcp"),
124
- "/usr/local/bin/kicad-sch-mcp"
125
- ]
126
-
127
- for path_to_try in possible_paths:
128
- if os.path.exists(path_to_try) and os.access(path_to_try, os.X_OK):
129
- print(f"✅ MCP command found at: {path_to_try}")
130
- print("⚠️ Note: Command not in PATH, but found at above location")
131
- mcp_cmd_path = path_to_try
132
- break
133
-
134
- if not mcp_cmd_path:
135
- print("❌ MCP command not found in PATH")
136
- print(" You may need to add Python scripts directory to your PATH")
137
- print(f" Try: export PATH=\"/Library/Frameworks/Python.framework/Versions/{python_version}/bin:$PATH\"")
138
-
139
- # Store found path for potential use in configuration
140
- if mcp_cmd_path:
141
- os.environ['FOUND_MCP_PATH'] = mcp_cmd_path
142
-
143
- # Check Claude Code configuration
144
- config_path = get_claude_config_path()
145
- if config_path.exists():
146
- try:
147
- with open(config_path) as f:
148
- config = json.load(f)
149
- if "kicad-sch-api" in config.get("mcpServers", {}):
150
- print("✅ Claude Code MCP configuration found")
151
- else:
152
- print("⚠️ Claude Code config exists but kicad-sch-api not configured")
153
- except json.JSONDecodeError:
154
- print("❌ Claude Code config file is invalid JSON")
155
- else:
156
- print("❌ Claude Code configuration not found")
157
-
64
+
158
65
  # Check KiCAD libraries
159
66
  try:
160
67
  from kicad_sch_api.library.cache import get_symbol_cache
68
+
161
69
  cache = get_symbol_cache()
162
70
  stats = cache.get_performance_stats()
163
- print(f"✅ KiCAD libraries: {len(cache._lib_stats)} libraries, {stats['total_symbols_cached']} symbols")
71
+ print(
72
+ f"✅ KiCAD libraries: {len(cache._lib_stats)} libraries, {stats['total_symbols_cached']} symbols"
73
+ )
164
74
  except Exception as e:
165
75
  print(f"⚠️ KiCAD library access: {e}")
166
-
76
+
167
77
  return True
168
78
 
79
+
169
80
  def create_demo() -> bool:
170
81
  """Create a demo schematic to test functionality."""
171
82
  print("🎨 Creating demo schematic...")
172
-
83
+
173
84
  try:
174
85
  import kicad_sch_api as ksa
175
-
86
+
176
87
  # Create demo schematic
177
88
  sch = ksa.create_schematic("Demo_Circuit")
178
-
89
+
179
90
  # Add components
180
- resistor = sch.components.add('Device:R', reference='R1', value='10k', position=(100, 100))
181
- capacitor = sch.components.add('Device:C', reference='C1', value='100nF', position=(150, 100))
182
- led = sch.components.add('Device:LED', reference='D1', value='LED', position=(200, 100))
183
-
184
- # Add a hierarchical sheet
185
- sheet_uuid = sch.add_sheet(
186
- name="Subcircuit",
187
- filename="subcircuit_demo.kicad_sch",
188
- position=(100, 150),
189
- size=(60, 40)
91
+ resistor = sch.components.add("Device:R", reference="R1", value="10k", position=(100, 100))
92
+ capacitor = sch.components.add(
93
+ "Device:C", reference="C1", value="100nF", position=(150, 100)
190
94
  )
191
-
192
- # Add sheet pins
193
- sch.add_sheet_pin(sheet_uuid, "VCC", "input", (0, 10))
194
- sch.add_sheet_pin(sheet_uuid, "GND", "input", (0, 30))
195
-
95
+ led = sch.components.add("Device:LED", reference="D1", value="LED", position=(200, 100))
96
+
196
97
  # Save schematic
197
98
  sch.save("demo_circuit.kicad_sch")
198
-
99
+
199
100
  print("✅ Demo schematic created: demo_circuit.kicad_sch")
200
- print("📁 Contains: resistor, capacitor, LED, and hierarchical sheet")
101
+ print("📁 Contains: resistor, capacitor, and LED")
201
102
  print("🔗 Try opening in KiCAD: kicad demo_circuit.kicad_sch")
202
-
103
+
203
104
  return True
204
-
105
+
205
106
  except Exception as e:
206
107
  print(f"❌ Demo creation failed: {e}")
207
108
  return False
208
109
 
110
+
209
111
  def init_cache() -> bool:
210
112
  """Initialize the component discovery cache."""
211
113
  print("🔄 Initializing component discovery cache...")
212
-
114
+
213
115
  try:
214
116
  from kicad_sch_api.discovery.search_index import ensure_index_built
117
+
215
118
  component_count = ensure_index_built()
216
119
  print(f"✅ Component cache initialized: {component_count} components indexed")
217
120
  return True
@@ -219,14 +122,14 @@ def init_cache() -> bool:
219
122
  print(f"❌ Cache initialization failed: {e}")
220
123
  return False
221
124
 
125
+
222
126
  def check_kicad() -> bool:
223
127
  """Check KiCAD installation and library access."""
224
128
  print("🔍 Checking KiCAD installation...")
225
-
129
+
226
130
  try:
227
131
  # Check if KiCAD command is available
228
- result = subprocess.run(['kicad', '--version'],
229
- capture_output=True, timeout=10)
132
+ result = subprocess.run(["kicad", "--version"], capture_output=True, timeout=10)
230
133
  if result.returncode == 0:
231
134
  version_output = result.stdout.decode().strip()
232
135
  print(f"✅ KiCAD found: {version_output}")
@@ -235,89 +138,37 @@ def check_kicad() -> bool:
235
138
  except (subprocess.TimeoutExpired, FileNotFoundError):
236
139
  print("❌ KiCAD command not found in PATH")
237
140
  print(" Please ensure KiCAD is installed and accessible")
238
-
141
+
239
142
  # Check library directories
240
143
  try:
241
144
  from kicad_sch_api.library.cache import get_symbol_cache
145
+
242
146
  cache = get_symbol_cache()
243
-
147
+
244
148
  print("📚 KiCAD Library Status:")
245
149
  for lib_name, lib_stats in cache._lib_stats.items():
246
150
  print(f" • {lib_name}: {lib_stats.symbol_count} symbols")
247
-
151
+
248
152
  return True
249
153
  except Exception as e:
250
154
  print(f"❌ Library access failed: {e}")
251
155
  return False
252
156
 
253
- def show_logs():
254
- """Show recent MCP server logs."""
255
- print("📜 Recent MCP Server Logs")
157
+
158
+ def show_mcp_info() -> None:
159
+ """Show information about MCP server integration."""
160
+ print("🤖 MCP Server Integration")
256
161
  print("=" * 25)
257
-
258
- # For now, just run the server with debug output
259
- print("To view live logs, run:")
260
- print(" kicad-sch-mcp --debug")
261
162
  print()
262
- print("Or check Claude Code logs in:")
263
- if sys.platform == "darwin":
264
- print(" ~/Library/Logs/Claude/mcp-server-kicad-sch-api.log")
265
- elif sys.platform == "win32":
266
- print(" %USERPROFILE%\\AppData\\Local\\Claude\\Logs\\mcp-server-kicad-sch-api.log")
267
- else:
268
- print(" ~/.local/share/Claude/logs/mcp-server-kicad-sch-api.log")
269
-
270
- def setup_everything() -> bool:
271
- """One-command setup that does everything automatically."""
272
- print("🚀 KiCAD Schematic API - Complete Setup")
273
- print("=" * 40)
163
+ print("This library serves as a foundation for MCP servers.")
164
+ print("For AI agent integration, install the dedicated MCP server:")
274
165
  print()
275
-
276
- success = True
277
-
278
- # 1. Test installation
279
- print("Step 1/4: Testing installation...")
280
- if not test_installation():
281
- print("❌ Installation test failed. Please reinstall the package.")
282
- return False
283
- print()
284
-
285
- # 2. Initialize cache
286
- print("Step 2/4: Initializing component cache...")
287
- if not init_cache():
288
- print("⚠️ Cache initialization failed, but continuing...")
289
- print()
290
-
291
- # 3. Setup Claude Code (using direct Python command)
292
- print("Step 3/4: Configuring Claude Code...")
293
- if not setup_claude_code():
294
- print("⚠️ Claude Code setup failed, but continuing...")
295
- print()
296
-
297
- # 4. Create demo
298
- print("Step 4/4: Creating demo schematic...")
299
- if not create_demo():
300
- print("⚠️ Demo creation failed, but setup is complete")
301
- print()
302
-
303
- # Final status
304
- print("🎉 Setup Complete!")
166
+ print(" pip install mcp-kicad-sch-api")
167
+ print(" code mcp install mcp-kicad-sch-api")
305
168
  print()
306
- print(" What was configured:")
307
- print(" • MCP server ready for Claude Code")
308
- print(" • Component discovery cache initialized")
309
- print(" • Demo schematic created")
310
- print()
311
- print("🚀 Next steps:")
312
- print("1. Restart Claude Code")
313
- print("2. Try: 'Create a voltage divider with two 10kΩ resistors'")
314
- print("3. Open demo_circuit.kicad_sch in KiCAD to see the example")
315
- print()
316
- print("🔍 To test manually:")
317
- print(" python -m kicad_sch_api.mcp.server --test")
318
- print()
319
-
320
- return True
169
+ print("Related projects:")
170
+ print(" • mcp-kicad-sch-api: https://github.com/circuit-synth/mcp-kicad-sch-api")
171
+ print(" • Claude Code: https://claude.ai/code")
321
172
 
322
173
 
323
174
  def main():
@@ -327,74 +178,70 @@ def main():
327
178
  formatter_class=argparse.RawDescriptionHelpFormatter,
328
179
  epilog="""
329
180
  Examples:
330
- kicad-sch-api --setup # Complete one-command setup (RECOMMENDED)
331
- kicad-sch-api --setup-claude-code # Configure Claude Code MCP settings only
332
- kicad-sch-api --test # Test installation
181
+ kicad-sch-api --test # Test library installation
333
182
  kicad-sch-api --demo # Create demo schematic
334
- """
183
+ kicad-sch-api --status # Show library status
184
+ """,
335
185
  )
336
-
337
- # Main setup options
338
- parser.add_argument('--setup', action='store_true',
339
- help='Complete one-command setup (RECOMMENDED)')
340
-
341
- # Setup options
342
- parser.add_argument('--setup-claude-code', action='store_true',
343
- help='Configure Claude Code MCP settings only')
344
- parser.add_argument('--test', action='store_true',
345
- help='Test that the installation is working')
346
- parser.add_argument('--status', action='store_true',
347
- help='Show detailed installation and configuration status')
348
- parser.add_argument('--demo', action='store_true',
349
- help='Create a demo schematic')
350
- parser.add_argument('--init-cache', action='store_true',
351
- help='Initialize component discovery cache')
352
- parser.add_argument('--check-kicad', action='store_true',
353
- help='Check KiCAD installation and libraries')
354
- parser.add_argument('--logs', action='store_true',
355
- help='Show recent MCP server logs')
356
-
186
+
187
+ # Main options
188
+ parser.add_argument("--test", action="store_true", help="Test that the library is working")
189
+ parser.add_argument("--status", action="store_true", help="Show library installation status")
190
+ parser.add_argument("--demo", action="store_true", help="Create a demo schematic")
191
+ parser.add_argument(
192
+ "--init-cache", action="store_true", help="Initialize component discovery cache"
193
+ )
194
+ parser.add_argument(
195
+ "--check-kicad", action="store_true", help="Check KiCAD installation and libraries"
196
+ )
197
+ parser.add_argument(
198
+ "--mcp-info", action="store_true", help="Show MCP server integration information"
199
+ )
200
+
357
201
  args = parser.parse_args()
358
-
359
- # If no arguments provided, suggest setup
202
+
203
+ # If no arguments provided, show help
360
204
  if not any(vars(args).values()):
361
205
  print("🚀 KiCAD Schematic API - Command Line Interface")
362
206
  print()
363
- print("🌟 RECOMMENDED: Complete setup:")
364
- print(" kicad-sch-api --setup")
207
+ print("This is a pure Python library for KiCAD schematic manipulation.")
208
+ print()
209
+ print("🧪 Test the installation:")
210
+ print(" kicad-sch-api --test")
211
+ print()
212
+ print("🎨 Create a demo schematic:")
213
+ print(" kicad-sch-api --demo")
214
+ print()
215
+ print("🤖 For AI agent integration:")
216
+ print(" kicad-sch-api --mcp-info")
365
217
  print()
366
- print("🆘 For help with all options:")
218
+ print("🆘 For all options:")
367
219
  print(" kicad-sch-api --help")
368
220
  return
369
-
221
+
370
222
  # Execute requested actions
371
223
  success = True
372
-
373
- if args.setup:
374
- success &= setup_everything()
375
-
376
- if args.setup_claude_code:
377
- success &= setup_claude_code()
378
-
224
+
379
225
  if args.test:
380
226
  success &= test_installation()
381
-
227
+
382
228
  if args.status:
383
229
  success &= show_status()
384
-
230
+
385
231
  if args.demo:
386
232
  success &= create_demo()
387
-
233
+
388
234
  if args.init_cache:
389
235
  success &= init_cache()
390
-
236
+
391
237
  if args.check_kicad:
392
238
  success &= check_kicad()
393
-
394
- if args.logs:
395
- show_logs()
396
-
239
+
240
+ if args.mcp_info:
241
+ show_mcp_info()
242
+
397
243
  sys.exit(0 if success else 1)
398
244
 
245
+
399
246
  if __name__ == "__main__":
400
- main()
247
+ main()