https://github.com/librepcb/librepcb-parts-generator
A collection of scripts to generate parts for the LibrePCB default library
https://github.com/librepcb/librepcb-parts-generator
Last synced: 12 months ago
JSON representation
A collection of scripts to generate parts for the LibrePCB default library
- Host: GitHub
- URL: https://github.com/librepcb/librepcb-parts-generator
- Owner: LibrePCB
- License: mit
- Created: 2018-07-20T15:21:37.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2025-04-20T12:23:36.000Z (about 1 year ago)
- Last Synced: 2025-06-18T07:28:44.469Z (12 months ago)
- Language: Python
- Homepage:
- Size: 6.98 MB
- Stars: 7
- Watchers: 7
- Forks: 16
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# LibrePCB Library Parts Generator Scripts
This is a collection of Python 3 based scripts to generate parts for the
[LibrePCB](https://librepcb.org) default library.
## Requirements
- Python 3.8+
- Dependencies in `pyproject.toml`
## Introduction / Concepts
While it's easy to create a one-off script to generate LibrePCB library
elements, you quickly run into some issues:
- If your output format does not match the canonical format used in LibrePCB,
your elements will be reformatted when opening them in the LibrePCB library
editor
- When using random UUIDs, regenerating the library element with adjusted
parameters will result in a completely new library element (since it gets a
new UUID)
- String concatenation results in messy and hard-to-modify generator scripts
This project uses a set of **entity wrapper types** that can be used to
generate the corresponding library element. It also includes **helpers for
things like number formatting** as well as **a caching system for stable
UUIDs**.
### Entity Types
The entity types can be imported from the `entities` module. Unfortunately
there's no API documentation so far, so you'll have to take a look at the
[source code](https://github.com/LibrePCB/librepcb-parts-generator/tree/master/entities)
or rely on IDE autocompletion for now.
For example, instead of writing a symbol generator like this:
```python
lines = []
lines.append('(librepcb_symbol {}'.format(uuid4()))
lines.append(' (name "{}")'.format("Demo Symbol"))
lines.append(' (description "{}")'.format("A simple symbol with two pins."))
lines.append(' (keywords "{}")'.format(','.join(["simple", "demo"]))
# ...
lines.append(' (pin {} (name "1")'.format(uuid4()))
lines.append(' (position -10.16 0.0) (rotation 0.0) (length 2.54)')
lines.append(' )')
lines.append(' (pin {} (name "2")'.format(uuid4()))
lines.append(' (position 10.16 0.0) (rotation 180.0) (length 2.54)')
lines.append(' )')
# ...
print('\n'.join(lines))
```
...you can do something like this:
```python
from entities.common import Name, Description, Keywords, Position, Rotation, Length
from entities.symbol import Symbol, Pin
# Create symbol
symbol = Symbol(
str(uuid4()),
Name("Demo Symbol"),
Description("A simple symbol with two pins."),
Keywords("simple,demo"),
# ...
)
# Add pins
symbol.add_pin(Pin(str(uuid4()), Name("1"), Position(-10.16, 0.0), Rotation(0.0), Length(2.54)))
symbol.add_pin(Pin(str(uuid4()), Name("2"), Position(10.16, 0.0), Rotation(180.0), Length(2.54)))
# ...
# Print library element
print(str(symbol))
```
This is much easier to write, read and maintain. Furthermore, since the
entities are fully type annotated, you even benefit from type checking using
[mypy](http://mypy-lang.org/)!
### UUID Caching
In every generator script, you should first initialize the UUID cache:
```python
from common import init_cache, save_cache
# Initialize UUID cache, load any pre-existing entries
uuid_cache_file = 'uuid_cache_chip.csv'
uuid_cache = init_cache(uuid_cache_file)
```
The cache is a simple in-memory dictionary. The `init_cache` function will load
any pre-existing cache entries from the file system.
Every generated UUID should have its own stable lookup key. Depending on the
script, a wrapper function that generates missing UUIDs on the fly might make
sense:
```python
def uuid(category: str, full_name: str, identifier: str, create: bool = True) -> str:
"""
Return a UUID for the specified element.
Params:
category:
For example 'cmp' or 'pkg'.
full_name:
For example "RESC3216X65".
identifier:
For example 'pad-1' or 'pin-13'.
"""
key = '{}-{}-{}'.format(category, full_name, identifier).lower().replace(' ', '~')
if key not in uuid_cache:
if not create:
raise ValueError('Unknown UUID: {}'.format(key))
uuid_cache[key] = str(uuid4())
return uuid_cache[key]
pad_uuids = [
uuid('pkg', 'RESC3216X65', 'pad-1'),
uuid('pkg', 'RESC3216X65', 'pad-2'),
]
```
At the end of the generator script, all cached UUIDs should be persisted to the
file system.
```python
# Persist the cache to the file system
save_cache(uuid_cache_file, uuid_cache)
```
## Testing
Run the tests using pytest:
$ pytest
## License
MIT, see `LICENSE` file