Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
2126c3284This file is pinned to the selected release. Download the original to open it in your design tool.
[build-system]
# PEP 639 bare license string (`license = "MIT"`) requires setuptools >= 77.
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"
[project]
# PyPI dist name: the distribution ships as `akcli-kicad` while the import
# package and CLI stay `akcli` (see src/akcli/__init__.py name cascade);
# keep the three in lockstep.
name = "akcli-kicad"
version = "0.22.0"
description = "AI-native schematic design agent, purpose-built for KiCad: draw and edit .kicad_sch from JSON op-lists with net-diff safety rails, run ERC/design/intent checks, simulate on bundled ngspice, source parts, and import Altium .SchDoc/.PcbDoc read-only into the KiCad flow."
requires-python = ">=3.11"
readme = "README.md"
license = "MIT"
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: Manufacturing",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Operating System :: OS Independent",
]
[project.urls]
Homepage = "https://github.com/tipoLi5890/akcli"
Repository = "https://github.com/tipoLi5890/akcli.git"
Changelog = "https://github.com/tipoLi5890/akcli/blob/main/CHANGELOG.md"
[project.scripts]
akcli = "akcli.cli:main"
[project.optional-dependencies]
dev = ["pytest>=8", "jsonschema>=4", "build", "twine", "ruff>=0.15", "mypy>=1.10"]
[tool.setuptools.packages.find]
where = ["src"]
[tool.setuptools.package-data]
"akcli.webui" = ["*.html"]
"akcli.schemas" = ["*.json"]
# examples/circuits/*/ops.json mirrored by tools/examples_mirror.py; loaded at
# runtime via Path(__file__) so `project new --example` works from a wheel.
"akcli.examples" = ["*/ops.json"]
# sim/builtin.lib is loaded at runtime via Path(__file__); it MUST ship in the
# wheel or `akcli sim` with a builtin model breaks on a non-editable install.
"akcli.sim" = ["*.lib"]
# vendored MIT library — ship its license/provenance for compliance.
"akcli._vendor.jlc2kicadlib" = ["LICENSE", "PROVENANCE.md"]
[tool.ruff]
# Vendored jlc2kicadlib is kept byte-close to upstream; never lint it.
extend-exclude = ["src/akcli/_vendor"]
[tool.ruff.lint]
select = ["E4", "E7", "E9", "F", "W"]
[tool.ruff.lint.per-file-ignores]
# `l` is inductance throughout the calc domain, not an ambiguous name.
"src/akcli/calc/electrical.py" = ["E741"]
"src/akcli/calc/power.py" = ["E741"]
# Grandfathered spare imports/f-strings; clean up at next functional touch
# rather than churning otherwise-untouched modules for the lint gate.
"src/akcli/calc/registry.py" = ["F401"]
"src/akcli/calc/regulator.py" = ["F401"]
"src/akcli/ops/__init__.py" = ["F401"]
"src/akcli/parts/bom_jlc.py" = ["F401", "F541"]
# Deliberate compact paired coordinate statements in the S-expression writer.
"src/akcli/writers/properties.py" = ["E702"]
# Tests favor readability: spare imports/locals and compact fuzz mutators are fine.
"tests/**" = ["E702", "E741", "F401", "F841"]
[tool.mypy]
# Beachhead: gate packages module-by-module as each is brought up to the bar
# rather than the whole tree at once. Covered so far: the networked layer
# (parts), the calculators, the typed core (model/errors/units/safety/
# netdiff/journal/render_svg/kicad_escape/config/arrange), and the net/parse
# spine (netbuild, sexpr, checks/diff, geometry, arrange,
# intentgen), the symbol generator (symbol_spec + writers/symbol_lib),
# and the shared classification vocabulary (classify).
files = [
"src/akcli/parts", "src/akcli/calc",
"src/akcli/classify.py", "src/akcli/si_prefix.py", "src/akcli/contract.py",
"src/akcli/model.py", "src/akcli/errors.py", "src/akcli/units.py",
"src/akcli/safety.py", "src/akcli/netdiff.py", "src/akcli/journal.py",
"src/akcli/render_svg.py", "src/akcli/render_art.py",
"src/akcli/kicad_escape.py",
"src/akcli/config.py", "src/akcli/arrange",
"src/akcli/netbuild.py", "src/akcli/sexpr/parser.py", "src/akcli/sexpr/__init__.py", "src/akcli/sexpr/query.py",
"src/akcli/sexpr/build.py",
"src/akcli/checks/diff.py", "src/akcli/geometry",
"src/akcli/intentgen.py",
# 0.21 R4: the write-pipeline engines are born typed (as is every module
# extracted alongside them).
"src/akcli/pipeline",
"src/akcli/writers/blank.py", "src/akcli/writers/backups.py",
"src/akcli/symbol_spec.py", "src/akcli/writers/symbol_lib.py", "src/akcli/writers/identity.py",
# 0.21 R7: the op vocabulary is DATA (mypy --strict clean) and the
# generated schemas are views of it.
"src/akcli/opspec.py",
# 0.21 R8: `net --why`'s diagnosis engine, extracted from commands/query.
"src/akcli/explain.py",
# 0.22: the project-scaffolding engine is born typed, as is the
# degrade-only .kicad_pro reader and the packaged example index.
"src/akcli/scaffold.py",
"src/akcli/readers/kicad_pro.py",
"src/akcli/examples/__init__.py",
]
python_version = "3.11"
disallow_untyped_defs = true
disallow_incomplete_defs = true
warn_unused_ignores = true
warn_redundant_casts = true
warn_unreachable = true
no_implicit_optional = true
# parts/ imports ..model, ..checks.bom (untyped elsewhere in the tree); check
# call sites here but don't cascade errors into or require annotations on
# modules outside this beachhead.
follow_imports = "silent"
[[tool.mypy.overrides]]
# jlcsearch/EasyEDA JSON payloads are untyped `object`/`dict` by design (see
# module docstrings) — the defensive `getattr`/duck-typed opener plumbing
# isn't worth fighting the checker over for a first pass.
module = "akcli.parts.*"
disallow_untyped_calls = false
# ---------------------------------------------------------------------------
# pytest. Turning warnings into errors is the point: a DeprecationWarning from
# a stdlib API we depend on (the zero-dependency rule makes stdlib the WHOLE
# dependency surface) is a future Python-version breakage, and CI runs
# 3.11-3.14 — it must fail the suite the release before it fails the CLI
# instead of scrolling past in a summary line. Add a targeted `ignore::` entry
# WITH A COMMENT if a warning is genuinely out of our control.
# ---------------------------------------------------------------------------
[tool.pytest.ini_options]
testpaths = ["tests"]
filterwarnings = [
"error",
# ResourceWarning is emitted by the garbage collector, so *which* test it
# lands in depends on collection timing, not on the code under test — as an
# error it is a flaky, interpreter-version-dependent gate (and it fires
# from inside `__del__`, where pytest can only re-raise it as an
# unraisable-exception warning attached to an unrelated test).
"ignore::ResourceWarning",
]