Skip to content

devbisme/KiPart

Repository files navigation

KiPart

image

Generate multi-unit schematic symbols for KiCad from a CSV, text, Excel, or SPD file.

Features

  • kipart generates schematic part libraries for KiCad from CSV or Excel files.
  • Converts one or more lists of pins in a file into a library of multi-unit schematic part symbols.
  • Each row of the file lists the number, name, type, style, and unit of a pin along with what side of the symbol to place the pin on.
  • Has several command-line options for controlling the arrangement and order of the pins.
  • Pins with the same name (e.g., GND) can be placed at the same location so they can all be tied to a net with a single connection.
  • Also includes kilib2csv for converting existing schematic part libraries into CSV files suitable for input to KiPart.
  • Also includes kilib2spd for converting existing schematic part libraries into SPD (Shorthand Part Descriptiion) files, so a library can be maintained in a compact, human-friendly format.
  • Also includes kilib2jpd for converting existing schematic part libraries into JPD (JSON Part Description) files, so a library can be maintained in an AI-friendly format.
  • Also includes spd2csv for converting Shorthand Part Description (SPD) files to CSV format which can then be turned into schematic part libraries.
  • Also includes spd2jpd and jpd2spd for converting between SPD and SPD files.
  • Also includes cmpparts for comparing the parts of two or more libraries and flagging discrepancies.

Example Use Case

From a user:

I had a very complex library for a microprocessor that I needed to refactor--- I needed to reorder hundreds of pins in a sane human-usable format. I thought I was going to have do it by hand in KiCAD's graphical symbol editor. I tried that, got very frustrated with all the clicking and dragging.

So I then:

  • searched and found this tool,
  • used kilib2csv to export my KiCAD lib to CSV,
  • imported the CSV in a spreadsheet program
  • edited the spreadsheet (mainly sorting the pins by function using the spreadsheet's sort() function),
  • exported the spreadsheet back to CSV,
  • used kipart to export back to KiCAD.

Boom! Usable part in minutes.

Installation

Simple enough:

pip install kipart

This will install eight command-line utilities:

  • kipart: The main utility for generating schematic symbols from rows of pin data stored in CSV or Excel files.
  • spd2csv: A utility for converting SPD (Shorthand Part Description) files to CSV format for use with KiPart.
  • kilib2csv: A utility for converting existing KiCad libraries into CSV files. This is useful for converting existing libraries into a format that can be used with KiPart.
  • kilib2spd: A utility for converting existing KiCad libraries into SPD files, which is the reverse of the spd2csv + kipart pipeline.
  • spd2jpd, jpd2spd, and kilib2jpd: Utilities for converting SPD files and KiCad libraries to and from JPD (JSON Part Description) files, for when a part is easier to handle as JSON than as text.
  • cmpparts: A utility for comparing the parts of two or more libraries and reporting what differs between them.

How the utilities fit together

A part reaches a KiCad .kicad_sym library along one path: a description consisting of rows of CSV or Excel data is converted by kipart into a symbol library. Part descriptions can also be stored in JPD or SPD formats which are convertible to CSV via the jpd2spd and spd2csv utilities. A KiCad library can be converted back to each of these formats using one of the kilib2* utilities. cmpparts sits off to the side, comparing the parts held in any of the .kicad_sym, .spd, or .jpd files.

flowchart LR
    JPD["JPD file<br/>(.jpd)"]
    SPD["SPD file<br/>(.spd)"]
    CSV["CSV / Excel<br/>(.csv .xlsx .xls)"]
    LIB["KiCad library<br/>(.kicad_sym)"]

    JPD -->|jpd2spd| SPD
    SPD -->|spd2jpd| JPD
    SPD -->|spd2csv| CSV
    CSV -->|kipart| LIB
    LIB -->|kilib2csv| CSV
    LIB -->|kilib2spd| SPD
    LIB -->|kilib2jpd| JPD

    CMP{{"cmpparts<br/>(compare parts)"}}
    JPD -.-> CMP
    SPD -.-> CMP
    LIB -.-> CMP
Loading

Usage

KiPart

KiPart is mainly intended to be used as a script:

usage: kipart [-h] [-o OUTPUT] [-w] [-m] [-1] [-s {row,num,name}] [-r] [--ccw] [--scrunch] [--side {left,right,top,bottom}] [--type TYPE] [--style STYLE] [--push PUSH] [-a ALT_DELIMITER] [-b]
              [--bundle-style {none,count,range}] [--hide-pin-num] [-j {left,center,right}] [-v]
              [input_files ...]

Convert CSV or Excel files into KiCad symbol libraries

positional arguments:
  input_files           Input symbol pin data CSV or Excel files (.csv, .xlsx, .xls). If no files are given, reads from stdin.

options:
  -h, --help            show this help message and exit
  -o, --output OUTPUT   Output KiCad symbol library file (.kicad_sym)
  -w, --overwrite       Allow overwriting of an existing symbol library
  -m, --merge           Merge symbols into an existing library rather than overwriting completely
  -1, --one-symbol      Ignore blank lines rather than starting a new symbol
  -s, --sort {row,num,name}
                        Sort the part pins by their entry order in the CSV file (row), their pin number (num), or their pin name (name)
  -r, --reverse         Sort pins in reverse order
  --ccw                 Arrange pins counter-clockwise around the symbol
  --scrunch             Compress symbol pins on the left/right sides underneath the top/bottom sides
  --side {left,right,top,bottom}
                        Default side for pins without a side specifier
  --type TYPE           Default type for pins without a type specifier (e.g., input, output, bidirectional, passive)
  --style STYLE         Default style for pins without a style specifier (e.g., line, inverted, clock)
  --push PUSH           Position of pin groups on each side (0.0=start, 0.5=centered, 1.0=end)
  -a, --alt-delimiter ALT_DELIMITER
                        Delimiter character for splitting pin names into alternatives
  -b, --bundle          Bundle identically-named power or ground input pins into single schematic pins
  --bundle-style {none,count,range}
                        When bundling pins, selects what is appended to the net name
  --hide-pin-num        Hide pin numbers
  -j, --justify {left,center,right}
                        Sets the justification on visible properties
  -v, --version         show program's version number and exit

The input to kipart is one or more CSV or Excel files. These contain the following items:

  1. The part name or number stands alone in the first column of a row.

  2. Part properties are listed on the following rows. Each property begins with a property name followed by a colon and the property value. The standard properties are:

    • Reference: The reference designator such as U.
    • Value: The part value (often the same as the name).
    • Footprint: The part's package type (e.g., QFP, BGA, etc.).
    • Datasheet: A URL to the part's datasheet.
    • Description: A description of the part.
    • Keywords: Keywords for searching for the part.
    • Filters: The footprint filters for the part.
    • Locked: I have no idea what this does...

    You can also list part properties with arbitrary names of your own choosing.

  3. After the properties, the next row contains the column headers. The required headers are Pin and Name. Optional columns are Unit, Side, Type, Style, and Hidden. These can be placed in any order and in any column.

  4. Immediately after the column headers, each succeeding row contains the following data for one of the part's pins: the pin number, name, unit identifier (if the schematic symbol will have multiple units), pin type and style. Each of these items should be entered in the same column as the corresponding header.

    • Pin numbers can be either numeric (e.g., 69) if the part is a DIP or QFP, or they can be alphanumeric (e.g., C10) for BGAs or CSPs. Using a * character instead of a pin number creates non-existent "gap" pins that can be used to visually separate the pins into groups. (This only works when the -s row sorting option is selected.)

    • Pin names can be any combination of letters, numbers and special characters (except a comma). If the pin name contains one or more delimiter characters specified with the -a option, then the name will be split at each delimiter and the resulting substrings will be entered as alternate pin functions.

    • The unit identifier can be blank or any combination of letters, numbers and special characters (except a comma). A separate unit will be generated in the schematic symbol for each distinct unit identifier.

    • The side column specifies the side of the symbol the pin will be placed on. The allowable values are:

      -   left
      -   right
      -   top
      -   bottom
      
    • The type column specifies the electrical type of the pin. The allowable values are:

      -   input, inp, in, clk
      -   output, outp, out
      -   bidirectional, bidir, bi, inout, io, iop
      -   tristate, tri, tri_state, tristate
      -   passive, pass
      -   free
      -   unspecified, un, analog
      -   power_in, pwr_in, pwrin, power, pwr, ground, gnd
      -   power_out, pwr_out, pwrout, pwr_o
      -   open_collector, opencollector, open_coll, opencoll, oc
      -   open_emitter, openemitter, open_emit, openemit, oe
      -   no_connect, noconnect, no_conn, noconn, nc
      
    • The style column specifies the graphic representation of the pin. The allowable pin styles are:

      -   line, <blank>
      -   inverted, inv, ~, #
      -   clock, clk, rising_clk
      -   inverted_clock, inv_clk, clk_b, clk_n, ~clk, #clk
      -   input_low, inp_low, in_lw, in_b, in_n, ~in, #in
      -   clock_low, clk_low, clk_lw, clk_b, clk_n, ~clk, #clk
      -   output_low, outp_low, out_lw, out_b, out_n, ~out, #out
      -   edge_clock_high
      -   non_logic, nl, analog
      
    • The hidden column specifies whether the pin is invisible. This can be one of 'y', 'yes', 't', 'true', or '1' to make it invisible, anything else makes it visible.

  5. A blank row ends the list of pins for the part.

  6. Multiple parts (each consisting of a name, properties, column header and pin data rows) separated by blank lines are allowed in a single CSV file. Each part will become a separate symbol in the KiCad library.

The -s option specifies the pin order on each side of the symbol:

  • -s row places the pins in the order they were entered into the file.
  • -s name places the pins in increasing order of their names.
  • -s num places the pins in increasing order of their pin numbers and arranged in a counter-clockwise fashion around the symbol starting from the upper-left corner.

The --reverse option reverses the sort order for the pins.

The --ccw option arranges the pins running counter-clockwise around the symbol starting from the upper-left corner. If this option is not enabled, the pins on the left/right sides will run from top to bottom and the pins on the top/bottom sides will run from left to right.

The --scrunch option will compress a three- or four-sided schematic symbol by moving the left and right columns of pins closer together so that their pin labels are shadowed by the pins on the top and bottom rows.

The --side, --type, and --style options set the default side, I/O type, and graphic style for pins that don't have these specified in the CSV file.

The --push option is used to set the position of the pins on each side of the schematic symbol box. A value of 0.0 pushes them to the upper-most or left-most position on the left/right or top/bottom sides. A value of 1.0 pushes them to the bottom-most or right-most position on the left/right or top/bottom sides. A value of 0.5 (the default) centers them.

Specifying the -b option will place multiple power input pins with the identical names at the same location such that they can all attach to the same net with a single connection. This is helpful for handling the multiple VCC and GND pins found on many high pin-count devices.

The -a option specifies a delimiter for splitting pin names into alternates. This is useful for parts with pins having multiple functions. For example, -a / will split the pin name IO1/SDA/MOSI into a pin named IO1 with two alternate names of SDA and MOSI. In this case, the alternate pins will have different names but the electrical types and styles will be the same. If alternate pins with different types and styles are needed, just create one or more rows with the same data as the primary pin but change the name, type, and style as needed.

The -w option is used to overwrite an existing library with any new parts from the file. The old contents of the library are lost.

The -m option is used to merge parts into an existing library. If a part with the same name already exists, the new part will only overwrite it if the -w flag is also used. Any existing parts in the library that are not overwritten are retained.

The --hide_pin_num option is used to hide pin numbers.

Examples

KiPart can process one or more input files. The simplest case is generating a symbol library from a single CSV file. The following command will process the file.csv file and place the symbols in file.kicad_sym:

kipart file.csv

This also works with multiple input files with a separate library created for each CSV file:

kipart file1.csv file2.csv  # Creates file1.kicad_sym and file2.kicad_sym.

Symbols from multiple CSV files can be placed into a single library using the -o option:

kipart file1.csv file2.csv -o total.kicad_sym

If total.kicad_sym already exists, the previous command will report that the file cannot be overwritten. Use the -w option to force the overwrite:

kipart file1.csv file2.csv -w -o total.kicad_sym

Symbol libraries can also be built incrementally using the -m option that merges symbols generated from one or more CSV files into an existing library:

kipart file3.csv file4.csv -m -o total.kicad_sym

Assume the following data for a single-unit part is placed into the example.csv file:

example_part_1
Pin,    Type,           Name
23,     input,          A5
90,     output,         B1
88,     bidirectional,  C3
56,     tristate,       D22
84,     tristate,       D3
16,     power_in,       VCC
5,      power_in,       GND
29,     power_in,       VCC
98,     power_in,       GND
99,     power_in,       VCC
59,     power_in,       GND

Then the command kipart example.csv will create a schematic symbol where the pins are arranged in the order of the rows in the CSV file they are on:

image

The command kipart -s num example.csv will create a schematic symbol where the pins are arranged by their pin numbers:

image

The command kipart -s name example.csv will create a schematic symbol where the pins are arranged by their names:

image

The command kipart -b example.csv will bundle power pins with identical names (like GND and VCC) into single pins like so:

image

Or you could divide the part into two units: one for I/O pins and the other for power pins by adding a Unit column like this:

example_part_2
Pin,    Unit,   Type,           Name
23,     IO,     input,          A5
90,     IO,     output,         B1
88,     IO,     bidirectional,  C3
56,     IO,     tristate,       D22
84,     IO,     tristate,       D3
16,     PWR,    power_in,       VCC
5,      PWR,    power_in,       GND
29,     PWR,    power_in,       VCC
98,     PWR,    power_in,       GND
99,     PWR,    power_in,       VCC
59,     PWR,    power_in,       GND

Then the command kipart -b example.csv results in a part symbol having two separate units:

image

image

As an alternative, you could go back to a single unit with all the inputs on the left side, all the outputs on the right side, the VCC pins on the top and the GND pins on the bottom:

example_part_3
Pin,    Unit,   Type,           Name,   Side
23,     1,      input,          A5,     left
90,     1,      output,         B1,     right
88,     1,      bidirectional,  C3,     left
56,     1,      tristate,       D22,    right
84,     1,      tristate,       D3,     right
16,     1,      power_in,       VCC,    top
5,      1,      power_in,       GND,    bottom
29,     1,      power_in,       VCC,    top
98,     1,      power_in,       GND,    bottom
99,     1,      power_in,       VCC,    top
59,     1,      power_in,       GND,    bottom

Running the command kipart -b example.csv generates a part symbol with pins on all four sides:

image

If the input file has a Hidden column, then some, none, or all pins can be made invisible:

a_part_with_secrets
Pin,    Name,   Type,   Side,   Style,      Hidden
1,      N.C.,   in,     left,   clk_low,    Y
2,      GND,    pwr,    left,   ,           yes
3,      SS_INH, in,     left,   ,           True
4,      OSC,    in,     left,   ,
5,      A1,     out,    right,  ,           False

In the Part Library Editor, hidden pins are grayed out:

image

But in Eeschema, they won't be visible at all:

image

There are two methods for arranging the pins around the periphery of the symbol. The default method is to place the pins running from top-to-bottom on the left and right sides and from left-to-right on the top and bottom sides. For a four-sided part, with the following pin data:

example_part_4
Pin,    Name,   Side
1,      P1,     left
2,      P2,     left
3,      P3,     left
4,      P4,     left
5,      P5,     left
6,      P6,     bottom
7,      P7,     bottom
8,      P8,     bottom
9,      P9,     bottom
10,     P10,    bottom
11,     P11,    right
12,     P12,    right
13,     P13,    right
14,     P14,    right
15,     P15,    right
16,     P16,    top
17,     P17,    top
18,     P18,    top
19,     P19,    top
20,     P20,    top

Then the command kipart example.csv -s num will result in the following symbol:

image

The pin arrangement shown above is often not what you want. The --ccw enables an alternative method where the pins are placed counter-clockwise starting from the upper-left corner. The command kipart example.csv -s num --ccw generates the following symbol:

image

The --scrunch option will compress the symbol by moving the left and right columns of pins closer together so that their pin labels are pushed under the pins on the top and bottom rows. Using kipart example.csv -s num --ccw --scrunch gives the following symbol:

image

spd2csv

If you have symbol definitions in SPD (Shorthand Part Description) format, you can convert them to CSV using the spd2csv utility.

usage: spd2csv [-h] [-o OUTPUT] [-m] [input_files ...]

Convert SPD symbol description files to CSV format for kipart.

positional arguments:
  input_files          SPD format input files (if none given, reads from stdin)

options:
  -h, --help           show this help message and exit
  -o, --output OUTPUT  Output CSV file (default: stdout)
  -m, --merge          Append to output file instead of overwriting

SPD files use a simple text format to define symbols, summarized below and described in full in SPD.md:

; Comment
device part_name
left
   pin_type  pin_name  pin_number
   pin_type  pin_name  pin_number
right
   pin_type  pin_name  pin_number
   pin_type  pin_name  pin_number
top
   ...
bottom
   ...

Full-line or in-line comments start with ;, or //. White space is ignored, so part descriptions can be indented for readability.

The side directives (left, right, top, bottom) control on which side of the symbol the subsequent pins are placed.

A pin type is composed of a code for the electrical type to which optional modifier characters can be added to set the graphical pin style and visibility:

Code KiCad Type
p, pi, pwr power_in
po, pwr_out power_out
i, in input
o, out output
b, bi, io bidirectional
t, tri tri_state
oc open_collector
oe open_emitter
pass passive
f free
u, un, a, analog unspecified
x, nc no_connect
Modifier Effect
* inverted
! inverted
~ inverted
> clock
_ low
@ analog
- hidden

Multiple modifiers can be combined (e.g., !> produces an inverted_clock, -!> produces an inverted_clock + hidden). The modifiers can be placed before or after the pin code.

If the same pin number is used more than once, the subsequent uses will define alternate pins, possibly with different names, electrical types, and styles. For example, the following will define pin 10 of a part to be a general-purpose I/O with an alternate function as a serial output:

io   GPIO1   10
o    TX      10

To create multiple pins from a single line, provide multiple pin numbers after the pin name:

device mypart
left
i       a0      1 2 3 4 5 6 7 8

This creates pins a0-a7 assigned to pin numbers 1-8. If the pin name ends with a number, the pin names will be automatically incremented (a0, a1, a2...). If the pin name does not end with a number, all pins get the same name (useful for things like VCC and GND pins).

To leave an empty position on a side of the symbol, insert a line containing only an *:

device mypart
left
i       vcc     1
*                   // pin spacer
i       gnd     3

This creates an empty pin position (spacer) between vcc and gnd on the left side. To leave several positions empty, repeat the asterisk (***) or give a count after it (*3).

Every line of an SPD file has to be a device line, a property, a unit or side directive, a spacer, or a pin. Anything else is reported as an error rather than being quietly skipped.

Symbols with multiple functional units are defined using the unit directive:

device mypart
unit A
    left
    i       a0      1 2 3
    right
    o       y0      4 5 6
unit B
    left
    i       b0      7 8 9
    right
    o       z0      10 11 12

The unit <name> directive assigns subsequent pins to that unit. Each unit becomes a separate section in the KiCad symbol. If no unit directive is present, the CSV output does not include a Unit column (single-unit symbol).

After the device line, you can specify part properties in the format name: value:

device mypart
Reference: U
Value: mypart
Footprint: SOP-8
Datasheet: https://example.com/datasheet.pdf
Description: A short description of the part
keywords: opamp analog
my_property_1: My very own property!
left
i       vcc     1
...

Below is a simple example of an SPD file:

;
; RT9818 reset (SOT-23)
;
device rt9818
Manf: Richtek

left
    a       vcc     3
    *
    a       gnd     2

right
    *
    *
    h       rst#    1

Convert and generate the symbol:

spd2csv rt9818.spd -o rt9818.csv
kipart rt9818.csv -o rt9818.kicad_sym

Or pipe directly to kipart:

spd2csv rt9818.spd | kipart -o rt9818.kicad_sym

kilib2csv

Sometimes you have existing libraries that you want to manage with a spreadsheet instead of the KiCad symbol editor. The kilib2csv utility takes one or more library files and converts them into a CSV file. Then the CSV file can be manipulated with a spreadsheet and used as input to KiPart. (Note that any stylized part symbol graphics will be lost in the conversion. KiPart only supports boring, box-like part symbols.)

usage: kilib2csv [-h] [-o OUTPUT] [-w] [-v] input_files [input_files ...]

Parse KiCad symbol libraries to CSV files

positional arguments:
input_files           Input KiCad symbol library files (.kicad_sym)

options:
-h, --help            show this help message and exit
-o OUTPUT, --output OUTPUT
                        Output CSV file path
-w, --overwrite       Allow overwriting of an existing CSV file
-v, --version         show program's version number and exit

A part that uses KiCad's extends keyword to borrow another part's pins is written out as a whole part, with the borrowed units and pins filled in and its own properties kept. kilib2spd and kilib2jpd do the same.

This utility handles single and multiple input files in the same manner as KiPart and supports some of the same options for overwriting and appending to the output CSV file:

kilib2csv my_lib1.lib my_lib2.lib -o my_library.csv

Then you can generate a consistent library from the CSV file:

kipart my_library.csv -o my_library_new.lib

kilib2spd

If you'd rather maintain an existing library in the compact SPD format, kilib2spd converts a KiCad symbol library into an SPD file. It's the reverse of the spd2csv + kipart pipeline, so the SPD file it writes can be fed straight back through those utilities to rebuild the library. (As with kilib2csv, any stylized part symbol graphics are lost in the conversion.)

usage: kilib2spd [-h] [-o OUTPUT] [-w] [--no-compress] [-v] input_files [input_files ...]

Convert KiCad symbol libraries into SPD (Shorthand Part Description) files

positional arguments:
input_files           Input KiCad symbol library files (.kicad_sym)

options:
-h, --help            show this help message and exit
-o OUTPUT, --output OUTPUT
                        Output SPD file path ('-' writes to stdout)
-w, --overwrite       Allow overwriting of an existing SPD file
--no-compress         Give each pin its own line instead of combining pins
                        that share a type, style, and name
-v, --version         show program's version number and exit

Convert a library into an SPD file, edit it, and rebuild the library:

kilib2spd my_library.kicad_sym          # Generates my_library.spd
spd2csv my_library.spd | kipart -o my_library_new.kicad_sym

By default, adjacent pins that share an electrical type, style, and visibility are combined onto a single line: pins with identical names (such as several GND pins) get listed as one name followed by all their pin numbers, and a run of pins whose names increment (a0, a1, a2...) collapses to the first name of the run. Use --no-compress to give every pin a line of its own.

Gaps between the pins on a side become * spacers, so the groupings within each side are preserved. Where the pins of a side sit as a whole along that side is not recorded, since KiPart re-derives that when it lays the symbol out again (see the --push option). Symbols built with kipart --bundle are also laid out slightly differently when rebuilt, because their bundled pins are stacked at a single location in the library.

Pin names and numbers containing whitespace can't be represented in SPD, and neither can a property name with a space in it; kilib2spd warns when it encounters them. A property name may hold anything else, Manf# included.

spd2jpd and jpd2spd

JPD (JSON Part Description) holds the same information as an SPD file, but as JSON, which is handier when a part is being generated or consumed by another program. spd2jpd and jpd2spd convert between the two formats, and the full format is described in JPD.md.

usage: spd2jpd [-h] [-o OUTPUT] [-w] [-v] input_files [input_files ...]
usage: jpd2spd [-h] [-o OUTPUT] [-w] [-v] input_files [input_files ...]

positional arguments:
input_files           Input files to convert

options:
-h, --help            show this help message and exit
-o OUTPUT, --output OUTPUT
                        Output file path ('-' writes to stdout)
-w, --overwrite       Allow overwriting of an existing output file
-v, --version         show program's version number and exit
spd2jpd part.spd            # Generates part.jpd
jpd2spd part.jpd            # Generates part.spd

SPD remains the route to a KiCad library, so a JPD file gets there by way of jpd2spd:

jpd2spd -o - part.jpd | spd2csv | kipart -o part.kicad_sym

The two formats hold the same information, so a part survives the trip in either direction. Comments are the exception: JSON has none, so the comments in an SPD file are lost on the way to JPD.

kilib2jpd

kilib2jpd reads a KiCad symbol library and writes the JPD description of the parts in it, which is what kilib2spd | spd2jpd would do in two steps:

kilib2jpd my_library.kicad_sym          # Generates my_library.jpd
kilib2jpd -o - my_library.kicad_sym     # Writes the JPD to stdout

What the library says about each part comes across — its pins, their names, types, styles, and alternates, and the properties of the part. The geometry the symbol is drawn with does not, since JPD has no way to say it and KiPart lays a symbol out afresh from the description anyway. That makes the JPD file a description of what the part is, free of how any one library chose to draw it, which is what cmpparts compares.

cmpparts

cmpparts compares the parts of two or more libraries and reports what differs. The libraries can be .kicad_sym, .spd, or .jpd files, in any mix, so a symbol library can be checked against the SPD file it was built from:

cmpparts my_parts.spd my_library.kicad_sym

The first library is the one the others are compared against, so giving three libraries yields two comparisons rather than three. cmpparts exits with 1 if the libraries differ and 0 if they don't, which is enough to make it a check in a build.

A pair of libraries to try it on lives in tests/examples. cmp_a.spd and cmp_b.spd hold the same six parts with one difference of every kind between them — a part that's identical, one whose pins are merely drawn in a different order, one with a dropped and a retyped pin, one that's been renamed and edited, and one apiece that the other library hasn't got:

cd tests/examples
make -f test.mk cmp_a.kicad_sym cmp_b.kicad_sym

cmpparts cmp_a.kicad_sym cmp_b.kicad_sym                 # everything
cmpparts -g cmp_a.kicad_sym cmp_b.kicad_sym              # only what the parts are
cmpparts -g -m fuzzy cmp_a.kicad_sym cmp_b.kicad_sym     # pairs the renamed part up
cmpparts -g -m fuzzy -f rich cmp_a.kicad_sym cmp_b.kicad_sym    # as a table
cmpparts -g -m fuzzy -f html cmp_a.kicad_sym cmp_b.kicad_sym    # in the browser

The two .spd files can be compared directly as well, without building anything, and say the same thing.

usage: cmpparts [-h] [-g] [-i CATEGORY] [-m {exact,normalized,fuzzy,pins}]
                [-t THRESHOLD] [-a OLD=NEW] [-f {text,rich,html,json}]
                [-o FILE] [--no-browser] [--wide] [--verbose] [-v]
                FILE FILE [FILE ...]

positional arguments:
FILE                  The libraries to compare (.kicad_sym, .spd, or .jpd)

options:
-h, --help            show this help message and exit
-g, --ignore-geometry
                        Ignore where the pins sit, how long they are, and how
                        big the body is, comparing only what the part is
-i CATEGORY, --ignore CATEGORY
                        Something to leave out of the comparison, given once
                        per entry: names, properties, geometry, units
-m, --match {exact,normalized,fuzzy,pins}
                        How to pair parts up across libraries
-t THRESHOLD, --threshold THRESHOLD
                        How alike two parts must be for '--match fuzzy' or
                        '--match pins' to pair them, from 0 to 1 (default: 0.6)
-a OLD=NEW, --alias OLD=NEW
                        Pair up a part of the first library with a differently
                        named part of the others
-f, --format {text,rich,html,json}
                        How to write the report: 'text' (the default), 'rich'
                        for a table in the terminal, 'html' for a table in the
                        browser, or 'json' for another program to read
-o FILE, --output FILE
                        Where to write the report. An HTML report goes to a
                        temporary file and is opened in the browser unless this
                        says otherwise; the other formats go to stdout.
--no-browser          Write the HTML report without opening it in the browser
--wide                Stretch the rich table across the terminal instead of
                        drawing it only as wide as its contents need
--verbose             Name the parts that came out identical, not just the
                        differing ones
-v, --version         show program's version number and exit

Ignoring the geometry

Where a pin sits, how long it is, and how big the symbol body is say nothing about what the part is, and only a .kicad_sym file records them at all. Two libraries built from the same pinout with different --push or --bundle settings differ in every pin position while describing the very same part. --ignore-geometry (or -g) leaves all of that out and compares the electrical description alone — the pins, their names, types, styles, visibility, and alternates, and the properties of the part:

cmpparts -g old_library.kicad_sym new_library.kicad_sym

Differences are reported in four categories, of which three can be ignored:

Category What it covers Ignorable
pins Pins, and their names, types, styles, visibility, and alternates no
properties The properties of a part yes
names Part and unit names yes
geometry Which side a pin is on, where it sits, and the body of the symbol yes

Each comparison uses only what both files know. Comparing an SPD file against a .kicad_sym file compares everything but the coordinates, which the SPD file hasn't got; comparing two SPD files still notices a pin that moved to another side or changed its place in the order.

Ignoring the units

How a part is split into units is a drawing decision, not a fact about the part: a quad NAND gate drawn as four gate units and a power unit has the same fourteen pins as one drawn as a single block. -i units sets the unit boundaries aside and compares the pins of each part as one table, so a pin that moved from one unit to another is no longer a difference:

cmpparts -g -i units split_library.kicad_sym flat_library.kicad_sym

units isn't a category of difference like the others — it's a way of comparing. With it, whether the units line up is no longer a question, so nothing about them is reported: neither a unit that only one part has, nor a unit that goes by another name. Everything about the pins themselves is still compared, and a pin whose name, type, style, visibility, or alternates changed is still reported — only now without a unit to name it in:

part '74hc00':
    pin 2 ('b1') is only in the first part
    pin 3 type: 'output' != 'tri_state'
    pin 7 name: 'gnd' != 'vss'

A pin number that turns up in two units names a second function of the one pin, which is the rule a number re-used within a unit already follows.

Matching parts whose names don't agree

The same part is OPA2333 in one library and opa2333xdgk in another. How cmpparts pairs parts up across libraries is set by --match:

Mode Pairs up parts whose...
exact names are identical
normalized names agree once case and punctuation are set aside (the default)
fuzzy names are merely alike, by at least --threshold
pins pinouts are alike, by at least --threshold, whatever they're called

Matching is one-to-one, and a part is only ever paired with its closest counterpart. pins recognizes a part by the pins it has, which is what to reach for when the names have nothing in common:

cmpparts -g -m fuzzy vendor_library.kicad_sym my_library.kicad_sym
cmpparts -g -m pins -t 0.8 vendor_library.kicad_sym my_library.kicad_sym

A pairing can also be made by hand with --alias, whatever the match mode says:

cmpparts -g -a rt9818=XYZ-9999 -a opa2333=ABC-1234 mine.spd vendor.kicad_sym

Parts that get paired up under a name that isn't identical are still reported as differing by name — the pairing says they're the same part, not that they're spelled the same way. Use --ignore names to leave those out.

===== my_parts.spd vs vendor_library.kicad_sym =====
part 'opa2333' ~ 'OPA2333-xDGK' (matched, 78% alike):
    part name: 'opa2333' != 'OPA2333-xDGK'
    unit 'PWR':
        pin 4 name: 'vcc' != 'vss'
part 'rt9818' is only in my_parts.spd

1 part matched, 0 identical, 1 differing; 1 only in my_parts.spd, 0 only in vendor_library.kicad_sym

How the report is written

--format (or -f) chooses how the same report is presented:

Format What you get
text The report above, a difference per line, grouped by part and unit (the default)
rich The differences as a table in the terminal, drawn with rich
html The same table as an HTML page, opened in your browser
json The whole report as JSON, for another program to read

The two tabular formats give a column to each library, so what changed can be read across the row:

cmpparts -f rich -g -m fuzzy cmp_a.kicad_sym cmp_b.kicad_sym
cmp_a.kicad_sym vs cmp_b.kicad_sym
┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Part               ┃ Unit  ┃ Pin ┃ Difference        ┃ cmp_a.kicad_sym ┃ cmp_b.kicad_sym ┃
┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 74hc00             │ LOGIC │ 5   │ missing pin       │ b2              │ —               │
│                    │ LOGIC │ 6   │ type              │ output          │ tri_state       │
├────────────────────┼───────┼─────┼───────────────────┼─────────────────┼─────────────────┤
│ rt9818 ~ RT9818-33 │       │     │ part name         │ rt9818          │ RT9818-33       │
│                    │       │     │ property 'Manf'   │ —               │ Richtek         │
│                    │ 1     │ 1   │ missing alternate │ mr              │ —               │
│                    │ 1     │ 3   │ name              │ vcc             │ vdd             │
├────────────────────┼───────┼─────┼───────────────────┼─────────────────┼─────────────────┤
│ dac8551            │       │     │ missing part      │ dac8551         │ —               │
├────────────────────┼───────┼─────┼───────────────────┼─────────────────┼─────────────────┤
│ lm358              │       │     │ missing part      │ —               │ lm358           │
└────────────────────┴───────┴─────┴───────────────────┴─────────────────┴─────────────────┘
4 parts matched, 2 identical, 2 differing; 1 only in cmp_a.kicad_sym, 1 only in cmp_b.kicad_sym

A in a column means that library hasn't got the thing at all, and the colour of the entry in the Difference column says which category it falls into. A part paired up under a name that isn't identical is shown as rt9818 ~ RT9818-33.

The table is drawn only as wide as its contents need, rather than stretched across the terminal; --wide stretches it. The libraries are named in full on the line above it, so their columns can go by filename alone — a path in a column heading would drag the whole table out to match it.

-f html writes the same table as a self-contained HTML page and opens it in your browser:

cmpparts -f html -g lib_a.kicad_sym lib_b.kicad_sym

The page goes to a temporary file unless --output names one to keep, and --no-browser writes it without opening anything — which is what to use when the comparison runs somewhere with no browser to open, such as a build:

cmpparts -f html -g --no-browser -o differences.html lib_a.kicad_sym lib_b.kicad_sym

If there's no browser to be found, the page is still written and cmpparts says where it went, so it can be opened by hand:

Wrote /tmp/cmpparts-3mshuzrb.html
Warning: couldn't open a browser to show it. Open it yourself with:
    file:///tmp/cmpparts-3mshuzrb.html

The page is opened in your default web browser — the one xdg-settings get default-web-browser names — rather than being handed to the desktop's generic file opener. On Linux those are two different things: the generic opener gives a file:// page to whatever program claims the text/html file type, and that needn't be a browser at all. A mail client that registers itself for HTML (Thunderbird does) will swallow the page and show nothing, while reporting success. If a page still doesn't appear, that association is the first thing to look at:

xdg-mime query default text/html        # should name a browser, not a mail client
xdg-mime default brave-browser.desktop text/html     # to point it at one

--output works for the other formats too, --verbose adds the parts that came out identical to any of them, and the exit status is the same whichever is chosen.

About

Python package for generating multi-unit schematic symbols for KiCad from a CSV file.

Topics

Resources

License

Contributing

Stars

201 stars

Watchers

19 watching

Forks

Packages

 
 
 

Contributors

Languages