Loading files
This 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",
]
2126c3284This file is pinned to the selected release. Download the original to open it in your design tool.