Metadata-Version: 2.4
Name: python-kicad
Version: 0.6.0
Summary: Pydantic models and parsers for KiCad 6 and newer design files
Author: esophagoose
License-Expression: MIT
Project-URL: Homepage, https://github.com/esophagoose/python-kicad
Project-URL: Repository, https://github.com/esophagoose/python-kicad
Project-URL: Issues, https://github.com/esophagoose/python-kicad/issues
Keywords: kicad,eda,pcb,schematic,parser,pydantic
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic<3,>=2.10.6
Provides-Extra: dev
Requires-Dist: build>=1.2.2; extra == "dev"
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=6.2.1; extra == "dev"
Requires-Dist: twine>=6.1.0; extra == "dev"
Dynamic: license-file

# python-kicad

`python-kicad` provides Pydantic models and parsers for KiCad schematic,
PCB, and exported netlist files.

- KiCad 6 and newer
- Python 3.10 and newer
- No KiCad installation required
- MIT licensed

## Installation

```console
python -m pip install python-kicad
```

The distribution is named `python-kicad`, while the import package remains
`pykicad`:

```python
from pykicad import Pcb, Schematic, read_from_file

document = read_from_file("project.kicad_pcb")
if isinstance(document.model, Pcb):
    print(document.model.version)
    print(len(document.model.footprint))
elif isinstance(document.model, Schematic):
    print(document.model.version)
    print(len(document.model.symbols))
```

An older, unrelated distribution already uses the `pykicad` name on PyPI and
installs into the same Python import namespace. Do not install `pykicad` and
`python-kicad` into the same environment.

## JSON command line interface

Inspect any supported KiCad document without loading its S-expression syntax
into another tool:

```console
pykicad inspect project.kicad_pcb
pykicad json project.kicad_pcb
pykicad json reusable-footprint.kicad_mod
```

`python -m pykicad` provides the same commands. Both commands accept `-` for
UTF-8 standard input and `--compact` for single-line output:

```console
cat project.kicad_sch | pykicad inspect - --compact
```

Full exports use a versioned envelope:

```json
{
  "schema": "pykicad.document",
  "schema_version": 1,
  "document_type": "pcb",
  "document": {}
}
```

The semantic document uses plural collection names, omits absent optional
fields, and preserves unknown KiCad tags in an `extensions` object. PCB
footprints include resolved `reference` and `value` fields, pads include both
local `position` and board-level `absolute_position`, and PCB net references
use consistent `code`/`name` objects. Placed schematic symbols similarly expose
their resolved reference, value, and footprint.

The same data is available from Python:

```python
from pykicad import export_json_data, inspect_document, read_from_file

document = read_from_file("project.kicad_pcb")
payload = export_json_data(document)
summary = inspect_document(document)
```

### Bundled agent skill

The installed distribution includes a `pykicad-cli` agent skill with the CLI
workflow, query patterns, schema documentation, and a machine-readable JSON
Schema. Copy it into a repository's project skills with:

```console
pykicad skill copy .agents/skills
```

The destination parent defaults to `.agents/skills`, so `pykicad skill copy`
creates `.agents/skills/pykicad-cli`. The command refuses to overwrite an
existing skill directory.

The complete export is designed to compose with standard JSON tools instead of
providing a separate query language. For example:

```console
# Footprint references, values, and positions
pykicad json board.kicad_pcb | jq '.document.footprints[] | {reference, value, position}'

# Pads belonging to U1
pykicad json board.kicad_pcb | jq '.document.footprints[] | select(.reference == "U1") | .pads[]'

# Unique connected net names
pykicad json board.kicad_pcb | jq '[.document.footprints[].pads[].net.name] | map(select(. != null)) | unique'

# Placed schematic symbols
pykicad json design.kicad_sch | jq '.document.symbols[] | {reference, value, footprint, position}'

# Tracks and copper zones
pykicad json board.kicad_pcb | jq '{tracks: .document.tracks, zones: .document.zones}'
```

Schema version 1 guarantees the envelope and modeled semantic field names.
Additional modeled fields may be added compatibly; removing a field or changing
its meaning requires a new schema version. Contents of `extensions` are
best-effort and are not part of that compatibility guarantee. JSON export is
read-only and does not retain source whitespace, comments, quoting choices, or
exact numeric spelling.

## Supported documents

`read_from_file()` and `read_from_string()` return a `KicadDocument` containing
the parsed model and its original source. They recognize:

- `.kicad_pcb` board files as `Pcb`
- `.kicad_mod` footprint files as `Footprint`
- `.kicad_sch` schematic files as `Schematic`
- KiCad-exported S-expression netlists as `Netlist`

The parser uses one Pydantic model family for released KiCad 6 and newer file
variants. Unknown enum values and malformed S-expressions remain validation
errors.

```python
from pydantic import ValidationError
from pykicad import read_from_string

try:
    document = read_from_string(
        "(kicad_pcb (version 20240101) (generator pcbnew))"
    )
    board = document.model
except (ValueError, ValidationError) as error:
    print(f"Invalid KiCad document: {error}")
```

## Writing

Exact PCB round-tripping is available for an unchanged `KicadDocument` loaded
through `read_from_file()` or `read_from_string()`. New and modified PCB models
are written using canonical KiCad S-expression formatting:

```python
from pykicad import read_from_file, write_to_file

document = read_from_file("project.kicad_pcb")
write_to_file(document, "copy.kicad_pcb")
```

Use `PcbBuilder.create()` to construct an empty KiCad 10 board. Standalone
`.kicad_mod` footprints can also be read and written. Models remain declarative
data structures; document I/O, serialization, and authoring live in dedicated
modules. Schematic writing is not implemented.

Common authoring operations are available through builders:

```python
from pykicad import BoardSide, FootprintBuilder, PcbBuilder, write_to_file
from pykicad.models.base import Point
from pykicad.models.pcb import Position

board = PcbBuilder.create(copper_layer_count=4)
ground = board.ensure_net("GND")
board.add_via(Position(x=10, y=10), size=0.6, drill=0.3, net=ground)
board.add_graphic_rect(
    Point(x=0, y=0), Point(x=20, y=20), layer="Edge.Cuts"
)

footprint = FootprintBuilder.create("Example:Part")
footprint.set_reference("U1", at=Position(x=0, y=-2), layer="F.SilkS")
footprint.place(Position(x=5, y=5), side=BoardSide.BACK)
board.add_footprint(footprint.build())

write_to_file(board.build(), "authored.kicad_pcb")
```

Place a `.kicad_mod` file directly onto a board with a reference and pad-net
mapping. Each placement receives fresh identifiers, so the same file can be
reused safely:

```python
from pykicad import BoardSide, PcbBuilder, write_to_file
from pykicad.models.pcb import Position

board = PcbBuilder.create()
board.add_footprint_file(
    "Package_SO.pretty/SOIC-8.kicad_mod",
    reference="U1",
    at=Position(x=25, y=40, angle=90),
    side=BoardSide.BACK,
    pad_nets={"1": "GND", "8": "VCC"},
)
write_to_file(board.build(), "placed.kicad_pcb")
```

## Development

Create an environment and install the development dependencies:

```console
python -m pip install -e ".[dev]"
python -m pytest
```

Build and validate release artifacts with:

```console
python -m build
python -m twine check dist/*
python scripts/check_distribution.py dist/*
```

See [RELEASING.md](RELEASING.md) for the trusted-publishing release process.
