Skip to content

feat: Add JLCPCB component import for LCSC part numbers - #616

Open
paycheckpacheck wants to merge 1 commit into
circuit-synth:mainfrom
paycheckpacheck:feat/jlc-import-components
Open

feat: Add JLCPCB component import for LCSC part numbers#616
paycheckpacheck wants to merge 1 commit into
circuit-synth:mainfrom
paycheckpacheck:feat/jlc-import-components

Conversation

@paycheckpacheck

Copy link
Copy Markdown

Summary

Adds support for importing JLCPCB/LCSC parts as circuit-synth components. Until now the JLCPCB integration could search for parts and print a code snippet, but there was no supported way to go from an LCSC part number to a Component object with the sourcing data attached.

New module: src/circuit_synth/manufacturing/jlcpcb/component_import.py.

Public API

from circuit_synth.manufacturing.jlcpcb import import_jlc_component

r1 = import_jlc_component("C25804")
# Component(symbol="Device:R", ref="R", value="10K",
#           footprint="Resistor_SMD:R_0603_1608Metric",
#           LCSC="C25804", MPN="RC0603FR-0710KL", Manufacturer="YAGEO",
#           JLCPCB_Stock="956234", JLCPCB_Part_Type="Basic")
  • import_jlc_component(lcsc_part, ref=None, symbol=None, footprint=None, value=None, **properties) -> Component - look up an LCSC part number and build the component.
  • component_from_search_result(result, ...) -> Component - build a component from an existing FastSearchResult without performing another lookup (works with cached results).
  • lookup_lcsc_part(lcsc_part) -> Optional[JlcPartSpec] - non raising lookup for callers that want to fall back to a locally specified component.
  • JlcComponentImporter - injectable class holding the search backend and the KiCad mapping provider; resolve_part(), spec_from_search_result(), spec_from_catalog_entry(), build_component(), import_component().
  • JlcPartSpec - resolved part data with to_properties() and to_circuit_synth_code().
  • normalize_lcsc_part() and the error hierarchy JlcImportError -> JlcPartNotFoundError, JlcLookupError, SymbolResolutionError.

Symbol, footprint, value and reference prefix are resolved through the existing SmartComponentFinder mappings, whose lookup helpers are now public methods (find_kicad_symbol, find_kicad_footprint, reference_designator_for, is_passive_component, extract_component_value) instead of being duplicated.

Component properties attached: LCSC, MPN, Manufacturer, JLCPCB_Package, JLCPCB_Price, JLCPCB_Stock, JLCPCB_Part_Type (Basic or Extended). Properties without data are omitted.

CLI

jlc-fast import C25804            # resolved part data plus the Component definition
jlc-fast import C25804 --json     # machine readable output
jlc-fast import C999999 --symbol Device:R

Degradation behavior

  • Search backend exceptions are wrapped in JlcLookupError, so an unavailable or rate limited JLCPCB endpoint does not surface as an arbitrary exception; lookup_lcsc_part() returns None and logs a warning.
  • No exact catalog match raises JlcPartNotFoundError (the CLI reports it and exits with status 1).
  • A missing footprint mapping logs a warning and still produces a component.
  • A missing symbol mapping raises SymbolResolutionError unless symbol= is supplied.

Testing

38 new tests, all with the JLCPCB search layer mocked, so no network access is required:

  • tests/unit/jlc_integration/test_jlc_component_import.py (33 tests) - part number normalization, symbol/footprint/value resolution for passives and ICs, property mapping, code generation, lookup success and failure paths, component construction, overrides and fallbacks.
  • tests/unit/tools/test_jlc_fast_search_cli.py (5 tests) - the new CLI command including the unknown part and unmapped symbol paths.
$ pytest tests/unit/jlc_integration tests/unit/test_fast_jlc_search.py \
         tests/integration/test_fast_jlc_integration.py tests/unit/tools
189 passed, 3 skipped, 2 warnings in 4.25s

The 3 skips are the pre-existing network dependent JLCPCB integration tests. black and isort report no changes on the touched files.

Adds circuit_synth.manufacturing.jlcpcb.component_import, which turns a
JLCPCB/LCSC catalog entry into a ready-to-use circuit-synth Component.

Public API:
- import_jlc_component(lcsc_part, ...) -> Component: look up an LCSC part
  number and build the component
- component_from_search_result(result, ...) -> Component: build a component
  from an existing FastSearchResult without another lookup
- lookup_lcsc_part(lcsc_part) -> Optional[JlcPartSpec]: non raising lookup for
  callers that need to fall back to a locally specified component
- JlcComponentImporter / JlcPartSpec for injection and reuse
- normalize_lcsc_part() plus a JlcImportError hierarchy
  (JlcPartNotFoundError, JlcLookupError, SymbolResolutionError)

The importer resolves the KiCad symbol, footprint, value and reference prefix
through the existing SmartComponentFinder mappings and attaches the sourcing
metadata as component properties: LCSC, MPN, Manufacturer, JLCPCB_Package,
JLCPCB_Price, JLCPCB_Stock and JLCPCB_Part_Type (Basic or Extended). Symbol,
footprint, value, reference and extra properties can be overridden by the
caller. A missing footprint mapping logs a warning and still produces a
component; a missing symbol mapping raises SymbolResolutionError unless a
symbol is supplied.

Search backend failures are wrapped in JlcLookupError so an unavailable or
rate limited JLCPCB endpoint does not surface as an arbitrary exception.

Also adds the `jlc-fast import <LCSC>` CLI command, which prints the resolved
part data and the generated Component definition, with a --json mode for
scripting, and promotes the SmartComponentFinder symbol/footprint mapping
helpers to public methods so they can be reused.

Tests: 33 unit tests for the importer and 5 for the CLI command, all with the
JLCPCB search layer mocked so no network access is required.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant