kicad-sch-api 0.0.2__py3-none-any.whl → 0.1.0__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.

Potentially problematic release.


This version of kicad-sch-api might be problematic. Click here for more details.

@@ -14,6 +14,8 @@ from dataclasses import dataclass, field
14
14
  from pathlib import Path
15
15
  from typing import Any, Dict, List, Optional, Set, Tuple, Union
16
16
 
17
+ import sexpdata
18
+
17
19
  from ..core.types import PinShape, PinType, Point, SchematicPin
18
20
  from ..utils.validation import ValidationError
19
21
 
@@ -37,6 +39,12 @@ class SymbolDefinition:
37
39
  power_symbol: bool = False
38
40
  graphic_elements: List[Dict[str, Any]] = field(default_factory=list)
39
41
 
42
+ # Raw KiCAD data for exact format preservation
43
+ raw_kicad_data: Any = None
44
+
45
+ # Symbol inheritance
46
+ extends: Optional[str] = None # Parent symbol name if this symbol extends another
47
+
40
48
  # Performance metrics
41
49
  load_time: float = 0.0
42
50
  access_count: int = 0
@@ -254,15 +262,19 @@ class SymbolLibraryCache:
254
262
  Returns:
255
263
  Symbol definition if found, None otherwise
256
264
  """
265
+ logger.debug(f"🔧 CACHE: Requesting symbol: {lib_id}")
266
+
257
267
  # Check cache first
258
268
  if lib_id in self._symbols:
259
269
  self._cache_hits += 1
260
270
  symbol = self._symbols[lib_id]
261
271
  symbol.access_count += 1
262
272
  symbol.last_accessed = time.time()
273
+ logger.debug(f"🔧 CACHE: Cache hit for {lib_id}")
263
274
  return symbol
264
275
 
265
276
  # Cache miss - try to load symbol
277
+ logger.debug(f"🔧 CACHE: Cache miss for {lib_id}, loading...")
266
278
  self._cache_misses += 1
267
279
  return self._load_symbol(lib_id)
268
280
 
@@ -344,17 +356,22 @@ class SymbolLibraryCache:
344
356
 
345
357
  def _load_symbol(self, lib_id: str) -> Optional[SymbolDefinition]:
346
358
  """Load a single symbol from its library."""
359
+ logger.debug(f"🔧 LOAD: Loading symbol {lib_id}")
360
+
347
361
  if ":" not in lib_id:
348
- logger.warning(f"Invalid lib_id format: {lib_id}")
362
+ logger.warning(f"🔧 LOAD: Invalid lib_id format: {lib_id}")
349
363
  return None
350
364
 
351
365
  library_name, symbol_name = lib_id.split(":", 1)
366
+ logger.debug(f"🔧 LOAD: Library: {library_name}, Symbol: {symbol_name}")
352
367
 
353
368
  if library_name not in self._library_index:
354
- logger.warning(f"Library not found: {library_name}")
369
+ logger.warning(f"🔧 LOAD: Library not found: {library_name}")
370
+ logger.debug(f"🔧 LOAD: Available libraries: {list(self._library_index.keys())}")
355
371
  return None
356
372
 
357
373
  library_path = self._library_index[library_name]
374
+ logger.debug(f"🔧 LOAD: Library path: {library_path}")
358
375
  return self._load_symbol_from_library(library_path, lib_id)
359
376
 
360
377
  def _load_symbol_from_library(
@@ -364,22 +381,32 @@ class SymbolLibraryCache:
364
381
  start_time = time.time()
365
382
 
366
383
  try:
367
- # This is a simplified version - in reality, you'd parse the .kicad_sym file
368
- # For now, create a basic symbol definition
369
384
  library_name, symbol_name = lib_id.split(":", 1)
370
385
 
371
- # Create basic symbol definition
372
- # In a real implementation, this would parse the actual .kicad_sym file
386
+ # Parse the .kicad_sym file to find the symbol
387
+ symbol_data = self._parse_kicad_symbol_file(library_path, lib_id)
388
+ if not symbol_data:
389
+ logger.warning(f"Symbol {symbol_name} not found in {library_path}")
390
+ return None
391
+
392
+ # Create SymbolDefinition from parsed data
373
393
  symbol = SymbolDefinition(
374
394
  lib_id=lib_id,
375
395
  name=symbol_name,
376
396
  library=library_name,
377
- reference_prefix=self._guess_reference_prefix(symbol_name),
378
- description=f"{symbol_name} component",
379
- pins=[], # Would be loaded from actual file
397
+ reference_prefix=symbol_data.get("reference_prefix", "U"),
398
+ description=symbol_data.get("description", ""),
399
+ keywords=symbol_data.get("keywords", ""),
400
+ datasheet=symbol_data.get("datasheet", "~"),
401
+ pins=symbol_data.get("pins", []),
402
+ extends=symbol_data.get("extends"), # Store extends information
380
403
  load_time=time.time() - start_time,
381
404
  )
382
405
 
406
+ # Store the raw symbol data for later use in schematic generation
407
+ symbol.raw_kicad_data = symbol_data.get("raw_data", {})
408
+ logger.debug(f"🔧 CREATED: SymbolDefinition for {lib_id}, extends: {symbol.extends}")
409
+
383
410
  self._symbols[lib_id] = symbol
384
411
  self._symbol_index[symbol_name] = lib_id
385
412
  self._total_load_time += symbol.load_time
@@ -391,6 +418,285 @@ class SymbolLibraryCache:
391
418
  logger.error(f"Error loading symbol {lib_id} from {library_path}: {e}")
392
419
  return None
393
420
 
421
+ def _parse_kicad_symbol_file(self, library_path: Path, lib_id: str) -> Optional[Dict[str, Any]]:
422
+ """Parse a KiCAD .kicad_sym file to extract a specific symbol."""
423
+ try:
424
+ # Extract symbol name from lib_id
425
+ library_name, symbol_name = lib_id.split(":", 1)
426
+
427
+ with open(library_path, 'r', encoding='utf-8') as f:
428
+ content = f.read()
429
+
430
+ # Parse the S-expression with symbol preservation
431
+ parsed = sexpdata.loads(content, true=None, false=None, nil=None)
432
+ logger.debug(f"🔧 PARSE: Parsed library file with {len(parsed)} top-level items")
433
+
434
+ # Find the symbol we're looking for
435
+ symbol_data = self._find_symbol_in_parsed_data(parsed, symbol_name)
436
+ if not symbol_data:
437
+ logger.debug(f"🔧 PARSE: Symbol {symbol_name} not found in {library_path}")
438
+ return None
439
+
440
+ logger.debug(f"🔧 PARSE: Found symbol {symbol_name} in library")
441
+
442
+ # Extract the library name and symbol name for resolution
443
+ library_name, symbol_name = lib_id.split(":", 1)
444
+
445
+ # Check if this symbol extends another symbol
446
+ extends_symbol = self._check_extends_directive(symbol_data)
447
+ logger.debug(f"🔧 CACHE: Symbol {lib_id} extends: {extends_symbol}")
448
+
449
+ # If this symbol extends another, we need to resolve it
450
+ if extends_symbol:
451
+ resolved_symbol_data = self._resolve_extends_relationship(
452
+ symbol_data, extends_symbol, library_path, library_name
453
+ )
454
+ if resolved_symbol_data:
455
+ symbol_data = resolved_symbol_data
456
+ extends_symbol = None # Clear extends after resolution
457
+ logger.debug(f"🔧 CACHE: Resolved extends for {lib_id}")
458
+
459
+ # Extract symbol information
460
+ result = {
461
+ "raw_data": symbol_data, # Store the raw parsed data
462
+ "reference_prefix": "U", # Default
463
+ "description": "",
464
+ "keywords": "",
465
+ "datasheet": "~",
466
+ "pins": [],
467
+ "extends": extends_symbol # Should be None after resolution
468
+ }
469
+
470
+ # Extract properties from the symbol
471
+ for item in symbol_data[1:]:
472
+ if isinstance(item, list) and len(item) > 0:
473
+ if item[0] == sexpdata.Symbol('property'):
474
+ prop_name = item[1]
475
+ prop_value = item[2]
476
+
477
+ logger.debug(f"🔧 Processing property: {prop_name} = {prop_value}")
478
+ if prop_name == sexpdata.Symbol('Reference'):
479
+ result["reference_prefix"] = str(prop_value)
480
+ logger.debug(f"🔧 Set reference_prefix: {str(prop_value)}")
481
+ elif prop_name == sexpdata.Symbol('Description'):
482
+ result["Description"] = str(prop_value) # Keep original case
483
+ logger.debug(f"🔧 Set Description: {str(prop_value)}")
484
+ elif prop_name == sexpdata.Symbol('ki_keywords'):
485
+ result["keywords"] = str(prop_value)
486
+ elif prop_name == sexpdata.Symbol('Datasheet'):
487
+ result["Datasheet"] = str(prop_value) # Keep original case
488
+ logger.debug(f"🔧 Set Datasheet: {str(prop_value)}")
489
+
490
+ # Extract pins (this is simplified - pins are in symbol sub-definitions)
491
+ # For now, we'll extract pins from the actual symbol structure
492
+ result["pins"] = self._extract_pins_from_symbol(symbol_data)
493
+
494
+ return result
495
+
496
+ except Exception as e:
497
+ logger.error(f"Error parsing {library_path}: {e}")
498
+ return None
499
+
500
+ def _find_symbol_in_parsed_data(self, parsed_data: List, symbol_name: str) -> Optional[List]:
501
+ """Find a specific symbol in parsed KiCAD library data."""
502
+ logger.debug(f"🔧 FIND: Looking for symbol '{symbol_name}' in parsed data")
503
+
504
+ if not isinstance(parsed_data, list):
505
+ logger.debug(f"🔧 FIND: Parsed data is not a list: {type(parsed_data)}")
506
+ return None
507
+
508
+ # First, log all available symbols for debugging
509
+ available_symbols = []
510
+ for item in parsed_data:
511
+ if isinstance(item, list) and len(item) >= 2:
512
+ if item[0] == sexpdata.Symbol('symbol'):
513
+ available_symbols.append(str(item[1]).strip('"'))
514
+
515
+ logger.debug(f"🔧 FIND: Available symbols in library: {available_symbols[:10]}...") # Show first 10
516
+
517
+ # Search through the parsed data for the symbol
518
+ for item in parsed_data:
519
+ if isinstance(item, list) and len(item) >= 2:
520
+ if (item[0] == sexpdata.Symbol('symbol') and
521
+ len(item) > 1 and
522
+ str(item[1]).strip('"') == symbol_name):
523
+ logger.debug(f"🔧 FIND: Found symbol '{symbol_name}'")
524
+ return item
525
+
526
+ logger.debug(f"🔧 FIND: Symbol '{symbol_name}' not found in library")
527
+ return None
528
+
529
+ def _check_extends_directive(self, symbol_data: List) -> Optional[str]:
530
+ """Check if symbol has extends directive and return parent symbol name."""
531
+ if not isinstance(symbol_data, list):
532
+ return None
533
+
534
+ for item in symbol_data[1:]:
535
+ if isinstance(item, list) and len(item) >= 2:
536
+ if item[0] == sexpdata.Symbol('extends'):
537
+ parent_name = str(item[1]).strip('"')
538
+ logger.debug(f"Found extends directive: {parent_name}")
539
+ return parent_name
540
+ return None
541
+
542
+ def _resolve_extends_relationship(self, child_symbol_data: List, parent_name: str,
543
+ library_path: Path, library_name: str) -> Optional[List]:
544
+ """Resolve extends relationship by merging parent symbol into child."""
545
+ logger.debug(f"🔧 RESOLVE: Resolving extends {parent_name} for child symbol")
546
+
547
+ try:
548
+ # Load the parent symbol from the same library
549
+ with open(library_path, 'r', encoding='utf-8') as f:
550
+ content = f.read()
551
+
552
+ parsed = sexpdata.loads(content, true=None, false=None, nil=None)
553
+ parent_symbol_data = self._find_symbol_in_parsed_data(parsed, parent_name)
554
+
555
+ if not parent_symbol_data:
556
+ logger.warning(f"🔧 RESOLVE: Parent symbol {parent_name} not found in library")
557
+ return None
558
+
559
+ logger.debug(f"🔧 RESOLVE: Found parent symbol {parent_name}")
560
+
561
+ # Merge parent into child (adapt from circuit-synth logic)
562
+ merged_symbol = self._merge_parent_into_child(child_symbol_data, parent_symbol_data)
563
+ logger.debug(f"🔧 RESOLVE: Merged parent into child symbol")
564
+
565
+ return merged_symbol
566
+
567
+ except Exception as e:
568
+ logger.error(f"🔧 RESOLVE: Error resolving extends: {e}")
569
+ return None
570
+
571
+ def _merge_parent_into_child(self, child_data: List, parent_data: List) -> List:
572
+ """Merge parent symbol graphics and pins into child symbol."""
573
+ import copy
574
+
575
+ # Get child and parent symbol names for unit renaming
576
+ child_name = str(child_data[1]).strip('"') if len(child_data) > 1 else "Child"
577
+ parent_name = str(parent_data[1]).strip('"') if len(parent_data) > 1 else "Parent"
578
+
579
+ logger.debug(f"🔧 MERGE: Merging {parent_name} into {child_name}")
580
+
581
+ # Start with child symbol structure
582
+ merged = copy.deepcopy(child_data)
583
+
584
+ # Remove the extends directive from child
585
+ merged = [item for item in merged if not (
586
+ isinstance(item, list) and len(item) >= 2 and
587
+ item[0] == sexpdata.Symbol('extends')
588
+ )]
589
+
590
+ # Copy all graphics and unit definitions from parent
591
+ for item in parent_data[1:]:
592
+ if isinstance(item, list) and len(item) > 0:
593
+ # Copy symbol unit definitions (contain graphics and pins)
594
+ if item[0] == sexpdata.Symbol('symbol'):
595
+ # Rename unit from parent name to child name
596
+ unit_item = copy.deepcopy(item)
597
+ if len(unit_item) > 1:
598
+ old_unit_name = str(unit_item[1]).strip('"')
599
+ # Replace parent name with child name in unit name
600
+ new_unit_name = old_unit_name.replace(parent_name, child_name)
601
+ unit_item[1] = new_unit_name
602
+ logger.debug(f"🔧 MERGE: Renamed unit {old_unit_name} -> {new_unit_name}")
603
+ merged.append(unit_item)
604
+ # Copy other non-property elements (child properties override parent)
605
+ elif item[0] not in [sexpdata.Symbol('property')]:
606
+ merged.append(copy.deepcopy(item))
607
+
608
+ logger.debug(f"🔧 MERGE: Merged symbol has {len(merged)} elements")
609
+ return merged
610
+
611
+ def _extract_pins_from_symbol(self, symbol_data: List) -> List[SchematicPin]:
612
+ """Extract pins from symbol data."""
613
+ pins = []
614
+
615
+ # Look for symbol sub-definitions like "R_1_1" that contain pins
616
+ for item in symbol_data[1:]:
617
+ if isinstance(item, list) and len(item) > 0:
618
+ if item[0] == sexpdata.Symbol('symbol'):
619
+ # This is a symbol unit definition, look for pins
620
+ pins.extend(self._extract_pins_from_unit(item))
621
+
622
+ return pins
623
+
624
+ def _extract_pins_from_unit(self, unit_data: List) -> List[SchematicPin]:
625
+ """Extract pins from a symbol unit definition."""
626
+ pins = []
627
+
628
+ for item in unit_data[1:]:
629
+ if isinstance(item, list) and len(item) > 0:
630
+ if item[0] == sexpdata.Symbol('pin'):
631
+ pin = self._parse_pin_definition(item)
632
+ if pin:
633
+ pins.append(pin)
634
+
635
+ return pins
636
+
637
+ def _parse_pin_definition(self, pin_data: List) -> Optional[SchematicPin]:
638
+ """Parse a pin definition from KiCAD format."""
639
+ try:
640
+ # pin_data format: (pin passive line (at 0 3.81 270) (length 1.27) ...)
641
+ pin_type_str = str(pin_data[1]) if len(pin_data) > 1 else "passive"
642
+ pin_shape_str = str(pin_data[2]) if len(pin_data) > 2 else "line"
643
+
644
+ position = Point(0, 0)
645
+ length = 2.54
646
+ rotation = 0
647
+ name = "~"
648
+ number = "1"
649
+
650
+ # Parse pin attributes
651
+ for item in pin_data[3:]:
652
+ if isinstance(item, list) and len(item) > 0:
653
+ if item[0] == sexpdata.Symbol('at'):
654
+ # (at x y rotation)
655
+ if len(item) >= 3:
656
+ position = Point(float(item[1]), float(item[2]))
657
+ if len(item) >= 4:
658
+ rotation = float(item[3])
659
+ elif item[0] == sexpdata.Symbol('length'):
660
+ length = float(item[1])
661
+ elif item[0] == sexpdata.Symbol('name'):
662
+ name = str(item[1]).strip('"')
663
+ elif item[0] == sexpdata.Symbol('number'):
664
+ number = str(item[1]).strip('"')
665
+
666
+ # Map pin type
667
+ pin_type = PinType.PASSIVE
668
+ if pin_type_str == "input":
669
+ pin_type = PinType.INPUT
670
+ elif pin_type_str == "output":
671
+ pin_type = PinType.OUTPUT
672
+ elif pin_type_str == "bidirectional":
673
+ pin_type = PinType.BIDIRECTIONAL
674
+ elif pin_type_str == "power_in":
675
+ pin_type = PinType.POWER_IN
676
+ elif pin_type_str == "power_out":
677
+ pin_type = PinType.POWER_OUT
678
+
679
+ # Map pin shape
680
+ pin_shape = PinShape.LINE
681
+ if pin_shape_str == "inverted":
682
+ pin_shape = PinShape.INVERTED
683
+ elif pin_shape_str == "clock":
684
+ pin_shape = PinShape.CLOCK
685
+
686
+ return SchematicPin(
687
+ number=number,
688
+ name=name,
689
+ position=position,
690
+ pin_type=pin_type,
691
+ pin_shape=pin_shape,
692
+ length=length,
693
+ rotation=rotation,
694
+ )
695
+
696
+ except Exception as e:
697
+ logger.error(f"Error parsing pin definition: {e}")
698
+ return None
699
+
394
700
  def _load_library(self, library_path: Path) -> bool:
395
701
  """Load all symbols from a library file."""
396
702
  library_name = library_path.stem
@@ -471,6 +777,8 @@ class SymbolLibraryCache:
471
777
  Path("/usr/share/kicad/symbols"),
472
778
  Path("/usr/local/share/kicad/symbols"),
473
779
  Path.home() / ".local/share/kicad/symbols",
780
+ # macOS KiCAD.app bundle path
781
+ Path("/Applications/KiCad/KiCad.app/Contents/SharedSupport/symbols"),
474
782
  ]
475
783
  )
476
784
 
@@ -482,7 +790,10 @@ class SymbolLibraryCache:
482
790
  ]
483
791
  )
484
792
 
485
- return [path for path in search_paths if path.exists()]
793
+ logger.debug(f"Potential library search paths: {search_paths}")
794
+ existing_paths = [path for path in search_paths if path.exists()]
795
+ logger.debug(f"Existing library search paths: {existing_paths}")
796
+ return existing_paths
486
797
 
487
798
  def _load_persistent_index(self):
488
799
  """Load persistent symbol index from disk."""
@@ -87,7 +87,7 @@ class SchematicValidator:
87
87
  """
88
88
  self.strict = strict
89
89
  self.issues = []
90
- self._valid_reference_pattern = re.compile(r"^(#[A-Z]+[0-9]+|[A-Z]+[0-9]*)$")
90
+ self._valid_reference_pattern = re.compile(r"^(#[A-Z]+[0-9]+|[A-Z]+[0-9]*[A-Z]?)$")
91
91
  self._valid_lib_id_pattern = re.compile(r"^[^:]+:[^:]+$")
92
92
 
93
93
  def validate_schematic_data(self, schematic_data: Dict[str, Any]) -> List[ValidationIssue]:
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kicad-sch-api
3
- Version: 0.0.2
3
+ Version: 0.1.0
4
4
  Summary: Professional KiCAD schematic manipulation library with exact format preservation and AI agent integration
5
5
  Author-email: Circuit-Synth <info@circuit-synth.com>
6
6
  Maintainer-email: Circuit-Synth <info@circuit-synth.com>
7
- License: MIT
7
+ License-Expression: MIT
8
8
  Project-URL: Homepage, https://github.com/circuit-synth/kicad-sch-api
9
9
  Project-URL: Documentation, https://circuit-synth.github.io/kicad-sch-api/
10
10
  Project-URL: Repository, https://github.com/circuit-synth/kicad-sch-api.git
@@ -15,7 +15,6 @@ Classifier: Development Status :: 4 - Beta
15
15
  Classifier: Intended Audience :: Developers
16
16
  Classifier: Intended Audience :: Science/Research
17
17
  Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
18
- Classifier: License :: OSI Approved :: MIT License
19
18
  Classifier: Programming Language :: Python :: 3
20
19
  Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
@@ -59,13 +58,13 @@ Dynamic: license-file
59
58
 
60
59
  ## 🆚 vs. Existing Solutions
61
60
 
62
- | Feature | kicad-sch-api | kicad-skip | KiCAD Official API |
63
- |---------|---------------|------------|-------------------|
64
- | **Schematic Support** | ✅ Full | Full | ❌ PCB Only |
61
+ | Feature | kicad-sch-api | Other Solutions | KiCAD Official API |
62
+ |---------|---------------|-----------------|-------------------|
63
+ | **Schematic Support** | ✅ Full | ⚠️ Varies | ❌ PCB Only |
65
64
  | **Format Preservation** | ✅ Exact | ❌ Basic | N/A |
66
65
  | **Performance** | ✅ Optimized | ⚠️ Basic | N/A |
67
- | **Library Management** | ✅ Advanced | ⚠️ Basic | N/A |
68
- | **Runtime Dependencies** | ❌ None | None | ✅ KiCAD Required |
66
+ | **Library Management** | ✅ Advanced | ⚠️ Limited | N/A |
67
+ | **Runtime Dependencies** | ❌ None | ⚠️ Varies | ✅ KiCAD Required |
69
68
 
70
69
  ## 📦 Installation
71
70
 
@@ -89,22 +88,19 @@ npm run build
89
88
  ```python
90
89
  import kicad_sch_api as ksa
91
90
 
92
- # Load existing schematic
93
- sch = ksa.load_schematic('my_circuit.kicad_sch')
91
+ # Create new schematic
92
+ sch = ksa.create_schematic('My Circuit')
94
93
 
95
94
  # Add components
96
- resistor = sch.components.add('Device:R', ref='R1', value='10k', pos=(100, 100))
97
- capacitor = sch.components.add('Device:C', ref='C1', value='0.1uF', pos=(150, 100))
95
+ resistor = sch.components.add('Device:R', reference='R1', value='10k', position=(100, 100))
96
+ capacitor = sch.components.add('Device:C', reference='C1', value='0.1uF', position=(150, 100))
98
97
 
99
98
  # Update properties
100
99
  resistor.footprint = 'Resistor_SMD:R_0603_1608Metric'
101
100
  resistor.set_property('MPN', 'RC0603FR-0710KL')
102
101
 
103
- # Connect components
104
- sch.add_wire(resistor.get_pin_position('2'), capacitor.get_pin_position('1'))
105
-
106
102
  # Save with exact format preservation
107
- sch.save() # Preserves original formatting exactly
103
+ sch.save('my_circuit.kicad_sch')
108
104
  ```
109
105
 
110
106
  ### Advanced Operations
@@ -204,7 +200,7 @@ MIT License - see [LICENSE](LICENSE) for details.
204
200
  ## 🔗 Related Projects
205
201
 
206
202
  - **[circuit-synth](https://github.com/circuit-synth/circuit-synth)**: Comprehensive circuit design automation
207
- - **[kicad-skip](https://github.com/psychogenic/kicad-skip)**: Foundation S-expression parser
203
+ - **[sexpdata](https://github.com/jd-boyd/sexpdata)**: S-expression parsing library
208
204
 
209
205
  ---
210
206
 
@@ -0,0 +1,21 @@
1
+ kicad_sch_api/__init__.py,sha256=mogTeOic6O-WWOfpoRuBzPicVNha-gbdMrhJX4ir5PY,2821
2
+ kicad_sch_api/py.typed,sha256=e4ldqxwpY7pNDG1olbvj4HSKr8sZ9vxgA_2ek8xXn-Q,70
3
+ kicad_sch_api/core/__init__.py,sha256=ur_KeYBlGKl-e1hLpLdxAhGV2A-PCCGkcqd0r6KSeBA,566
4
+ kicad_sch_api/core/components.py,sha256=TiQrl7jdDTnuCWKdrlQC8-3b9PU58KoxTTnPX6VyZZk,24759
5
+ kicad_sch_api/core/formatter.py,sha256=WhJPII8-hd4ou3_4AYa4UB8704cEE8rLshhBhVHnY7I,14173
6
+ kicad_sch_api/core/ic_manager.py,sha256=5pw0FtUBXeF6afbiYej7kQe6ga32N4bNTScEHWYGq7A,7298
7
+ kicad_sch_api/core/junctions.py,sha256=p99iv8pBb-3oktVsTeHgjl7QkkZa9EeN32nSy4g23o4,6251
8
+ kicad_sch_api/core/parser.py,sha256=xVWzRwGPklROWe9_VoauVeoFsCZjKQGyo6AsSg0bqgU,44174
9
+ kicad_sch_api/core/schematic.py,sha256=JxOTHbASxcOVEFK2Ms1s7q7uERaKVQb0Ojomfyip99I,45176
10
+ kicad_sch_api/core/types.py,sha256=sn6_OnOKnNjc_6oXpASEfWI6f7oHsMyJaHk8kc3QFMk,12823
11
+ kicad_sch_api/core/wires.py,sha256=kvANBg79KxOd5TKZNpHbjMyouZbGwRKLPNz4ePvvHgk,8207
12
+ kicad_sch_api/library/__init__.py,sha256=NG9UTdcpn25Bl9tPsYs9ED7bvpaVPVdtLMbnxkQkOnU,250
13
+ kicad_sch_api/library/cache.py,sha256=NPJT-apWH_JfVG1aXJ0gDnfGu8es_2tYiyZr-chcTxY,33511
14
+ kicad_sch_api/utils/__init__.py,sha256=1V_yGgI7jro6MUc4Pviux_WIeJ1wmiYFID186SZwWLQ,277
15
+ kicad_sch_api/utils/validation.py,sha256=XlWGRZJb3cOPYpU9sLQQgC_NASwbi6W-LCN7PzUmaPY,15626
16
+ kicad_sch_api-0.1.0.dist-info/licenses/LICENSE,sha256=Em65Nvte1G9MHc0rHqtYuGkCPcshD588itTa358J6gs,1070
17
+ kicad_sch_api-0.1.0.dist-info/METADATA,sha256=LIRlM5Iev8fS3Elb0zynJXiZIwmIqmUqcaYmnKN8WdA,6674
18
+ kicad_sch_api-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ kicad_sch_api-0.1.0.dist-info/entry_points.txt,sha256=VWKsFi2Jv7G_tmio3cNVhhIBfv_OZFaKa-T_ED84lc8,57
20
+ kicad_sch_api-0.1.0.dist-info/top_level.txt,sha256=n0ex4gOJ1b_fARowcGqRzyOGZcHRhc5LZa6_vVgGxcI,14
21
+ kicad_sch_api-0.1.0.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- kicad_sch_api/__init__.py,sha256=mogTeOic6O-WWOfpoRuBzPicVNha-gbdMrhJX4ir5PY,2821
2
- kicad_sch_api/py.typed,sha256=e4ldqxwpY7pNDG1olbvj4HSKr8sZ9vxgA_2ek8xXn-Q,70
3
- kicad_sch_api/core/__init__.py,sha256=ur_KeYBlGKl-e1hLpLdxAhGV2A-PCCGkcqd0r6KSeBA,566
4
- kicad_sch_api/core/components.py,sha256=P_-qZPNpA8LAT0M3dLHFF6XSFyNAnSlcKjUf6aREdUo,22425
5
- kicad_sch_api/core/formatter.py,sha256=MVF3Hhc5ZVPyVDYnGcxb88q0x0UTr2DQa45gppiFqNk,11953
6
- kicad_sch_api/core/parser.py,sha256=Ao1j8JPWHGBkznUi9k-RO4_sLcCrkE_5ialSxZAd0cQ,17943
7
- kicad_sch_api/core/schematic.py,sha256=O76nZvj4qffHkFrMJV5Z35xU95efPW-_mtAD8Nni7ao,15553
8
- kicad_sch_api/core/types.py,sha256=VyzloTl4RbjMKj0TKu5rEZ-rtxtiT8nvQw8L6xawEvs,9980
9
- kicad_sch_api/library/__init__.py,sha256=NG9UTdcpn25Bl9tPsYs9ED7bvpaVPVdtLMbnxkQkOnU,250
10
- kicad_sch_api/library/cache.py,sha256=_JtzEGgO7ViIKF4W2zVrvmHQBIiosp9hOr9pG06Tw6I,18917
11
- kicad_sch_api/utils/__init__.py,sha256=1V_yGgI7jro6MUc4Pviux_WIeJ1wmiYFID186SZwWLQ,277
12
- kicad_sch_api/utils/validation.py,sha256=7QZBtPHKu24SA6Bhkj7M-rxs76AVQZWhISDfsJYfV_0,15620
13
- kicad_sch_api-0.0.2.dist-info/licenses/LICENSE,sha256=Em65Nvte1G9MHc0rHqtYuGkCPcshD588itTa358J6gs,1070
14
- kicad_sch_api-0.0.2.dist-info/METADATA,sha256=0wa5C_1GHCirtAdlUTh2Eqqa1AreZkeTts6WkQaNjd8,6810
15
- kicad_sch_api-0.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- kicad_sch_api-0.0.2.dist-info/entry_points.txt,sha256=VWKsFi2Jv7G_tmio3cNVhhIBfv_OZFaKa-T_ED84lc8,57
17
- kicad_sch_api-0.0.2.dist-info/top_level.txt,sha256=n0ex4gOJ1b_fARowcGqRzyOGZcHRhc5LZa6_vVgGxcI,14
18
- kicad_sch_api-0.0.2.dist-info/RECORD,,