Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
19672bc
Add UuidCache class
hephaisto Aug 16, 2026
e0cb1a7
Check for stale UUIDs
hephaisto Aug 16, 2026
9bcbd1e
Load context in cache constructor, disable creation without context
hephaisto Aug 21, 2026
7e7577f
Update readme
hephaisto Aug 16, 2026
f4bc696
Update generate_axial_tht
hephaisto Aug 16, 2026
eb1c1dd
update generate_capacitor_radial_tht.py
hephaisto Aug 16, 2026
b789fe3
Update generate_connectors.py
hephaisto Aug 30, 2026
511884a
Update generate_dip.py
hephaisto Aug 30, 2026
4c1569b
Fix model global variable in generate_dip_switches
hephaisto Aug 30, 2026
b88dc19
Update generate_dip_switches.py
hephaisto Aug 30, 2026
449e117
Update generate_do.py
hephaisto Aug 30, 2026
af6fd8a
Update generate_led.py
hephaisto Aug 30, 2026
70c43fe
Update generate_mosfet_dual.py
hephaisto Aug 30, 2026
6c93a64
Update generate_dpak.py
hephaisto Aug 30, 2026
b34496d
Update generate_qfp.py
hephaisto Aug 30, 2026
2829896
Update generate_mounting_holes.py
hephaisto Aug 30, 2026
fdb0978
Update generate_dfn.py
hephaisto Aug 30, 2026
ee29dc3
Update generate_so.py
hephaisto Aug 30, 2026
f683120
Prepare generate_sod.py
hephaisto Aug 30, 2026
ef65c2c
Update generate_sod.py
hephaisto Aug 30, 2026
493800d
Fix global variable in generate_tactile_switches
hephaisto Aug 30, 2026
065ae90
Update generate_tactile_switches.py
hephaisto Aug 30, 2026
fcbaa09
Update generate_screw_terminals.py
hephaisto Aug 30, 2026
aa13198
Update generate_molex_picoblade.py
hephaisto Aug 30, 2026
456ad50
Update generate_chip.py, add create parameter to get
hephaisto Aug 30, 2026
948a9ad
Update generate_jst_sh_connectors.py
hephaisto Aug 30, 2026
2ae21b7
Update generate_idc.py
hephaisto Aug 30, 2026
63827c1
Update generate_modules.py
hephaisto Aug 30, 2026
755b651
Update generate_stm_mcu.py
hephaisto Aug 30, 2026
f8c8347
Directly call cache in generate_capacitor_radial_tht.py
hephaisto Aug 30, 2026
571d7e6
Directly call cache in generate_axial_tht.py
hephaisto Aug 30, 2026
ee55848
Directly call cache in generate_dip.py
hephaisto Aug 30, 2026
54b7bf6
Directly call cache in generate_connectors.py
hephaisto Aug 30, 2026
a8cbeec
Directly call cache in generate_dip_switches.py
hephaisto Aug 30, 2026
f819179
Directly call cache in generate_do.py
hephaisto Aug 30, 2026
93161b5
Directly call cache in generate_led.py
hephaisto Aug 30, 2026
577e4fe
Directly call cache in generate_mosfet_dual.py
hephaisto Aug 30, 2026
fede54f
Directly call cache in generate_dpak.py
hephaisto Aug 30, 2026
8c28e4e
Directly call cache in generate_mounting_holes.py
hephaisto Aug 30, 2026
cf317ff
Directly call cache in generate_qfp.py
hephaisto Aug 30, 2026
d794970
Directly call cache in generate_dfn.py
hephaisto Aug 30, 2026
2ca5d98
Directly call cache in generate_screw_terminals.py
hephaisto Aug 30, 2026
592bef6
Directly call cache in generate_so.py
hephaisto Aug 30, 2026
014d58a
Directly call cache in generate_sod.py
hephaisto Aug 30, 2026
ef9ad68
Directly call cache in generate_tactile_switches.py
hephaisto Aug 30, 2026
2c052ed
Directly call cache in generate_molex_picoblade.py
hephaisto Aug 30, 2026
5e54244
Directly call cache in generate_jst_sh_connectors.py
hephaisto Aug 30, 2026
207771a
Directly call cache in generate_chip.py
hephaisto Aug 30, 2026
250de0c
Directly call cache in generate_idc.py
hephaisto Aug 30, 2026
8f25e2a
Directly call cache in generate_stm_mcu.py
hephaisto Aug 30, 2026
3e86ab5
Temporarily fix casadi version
hephaisto Aug 30, 2026
6d62b44
Remove manual check for stale uuids
hephaisto Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 1 addition & 20 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,4 @@ jobs:
-print0 | sort -z | xargs -t0L1 -I {} python {} --3d
- name: Check for diffs in UUID caches
run: git diff --exit-code
- name: Check for stale entries in UUID caches
run: |
stat --format="%s %n" *.csv | sort -k2 > sizes_before.txt
find . -maxdepth 1 -name '*.csv' \
-not -name 'uuid_cache_stm_mcu.csv' \
-not -name 'uuid_cache_connectors.csv' \
-not -name 'uuid_cache_dfn.csv' \
-not -name 'uuid_cache_dip.csv' \
-not -name 'uuid_cache_so.csv' \
-delete
find . -maxdepth 1 -name 'generate_*.py' \
-not -name 'generate_stm_mcu.py' \
-not -name 'generate_modules.py' \
-not -name 'generate_connectors.py' \
-not -name 'generate_dfn.py' \
-not -name 'generate_dip.py' \
-not -name 'generate_so.py' \
-print0 | sort -z | xargs -t0L1 python
stat --format="%s %n" *.csv | sort -k2 > sizes_after.txt
diff sizes_before.txt sizes_after.txt

28 changes: 7 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,16 @@ entities are fully type annotated, you even benefit from type checking using

### UUID Caching

In every generator script, you should first initialize the UUID cache:
In every generator script, you should cache UUID entries:

```python
from common import init_cache, save_cache
from common import UuidCache

# Initialize UUID cache, load any pre-existing entries
uuid_cache_file = 'uuid_cache_chip.csv'
uuid_cache = init_cache(uuid_cache_file)
with UuidCache('uuid_cache_chip.csv'):
# package generation
```

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:
Expand All @@ -116,27 +113,16 @@ def uuid(category: str, full_name: str, identifier: str, create: bool = True) ->
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]
return uuid_cache.get(category, full_name, identifier)

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)
```

At the end of the generator script, all cached UUIDs will be persisted to the
file system automatically.

## Testing

Expand Down
74 changes: 54 additions & 20 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,64 @@
import re
from datetime import datetime
from os import path
from uuid import uuid4

from typing import Any, Dict, List, OrderedDict, Union


def init_cache(uuid_cache_file: str) -> Dict[str, str]:
print('Loading cache: {}'.format(uuid_cache_file))
uuid_cache: OrderedDict[str, str] = collections.OrderedDict()
try:
with open(uuid_cache_file, 'r') as f:
reader = csv.reader(f, delimiter=',', quotechar='"')
for row in reader:
uuid_cache[row[0]] = row[1]
except FileNotFoundError:
pass
return uuid_cache


def save_cache(uuid_cache_file: str, uuid_cache: Dict[str, str]) -> None:
print('Saving cache: {}'.format(uuid_cache_file))
with open(uuid_cache_file, 'w') as f:
writer = csv.writer(f, delimiter=',', quotechar='"', lineterminator='\n')
for k, v in sorted(uuid_cache.items()):
writer.writerow([k, v])
print('Done, cached {} UUIDs'.format(len(uuid_cache)))
class UuidCache:
def __init__(self, filename: str, stale_check: bool = True):
self.filename = filename
self.used_keys: set[str] = set()
self.entered = False
self.stale_check = stale_check

self.data: OrderedDict[str, str] = collections.OrderedDict()
print(f'Loading cache: {filename}')
try:
with open(self.filename, 'r') as f:
reader = csv.reader(f, delimiter=',', quotechar='"')
for row in reader:
self.data[row[0]] = row[1]
except FileNotFoundError:
print('Cache file {filename} not found, building new cache')
print(f'Cache has {len(self.data)} entries')

def __enter__(self) -> 'UuidCache':
self.used_keys = set()
self.entered = True
return self

def __exit__(self, exception: Any, value: Any, traceback: Any) -> None:
if not exception and self.entered:
self.check_stale()
self.save_cache()

def save_cache(self) -> None:
print(f'Saving cache: {self.filename}')
with open(self.filename, 'w') as f:
writer = csv.writer(f, delimiter=',', quotechar='"', lineterminator='\n')
for k, v in sorted(self.data.items()):
writer.writerow([k, v])
print(f'Done, cached {len(self.data)} UUIDs')

def get(self, *args: Any, create: bool = True) -> str:
key = '-'.join(str(a).lower().replace(' ', '~') for a in args)
if key not in self.data:
if self.entered and create:
self.data[key] = str(uuid4())
else:
raise KeyError(
f'{key} not found in uuid cache. Entering the context is required for auto-generation'
)
self.used_keys.add(key)
return self.data[key]

def check_stale(self) -> None:
if self.stale_check:
stale_keys = {key for key in self.data if key not in self.used_keys}
if stale_keys:
raise RuntimeError(f'There are stale UUIDs in the cache: {stale_keys}')


def now() -> str:
Expand Down
23 changes: 8 additions & 15 deletions generate_axial_tht.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
import sys
from math import acos, asin, pi, sqrt
from os import path
from uuid import uuid4

from typing import Iterable, List, Optional, Tuple

from common import init_cache, now, save_cache
from common import UuidCache, now
from entities.common import (
Align,
Angle,
Expand Down Expand Up @@ -73,16 +72,7 @@
courtyard_excess = 0.4


# Initialize UUID cache
uuid_cache_file = 'uuid_cache_axial_tht.csv'
uuid_cache = init_cache(uuid_cache_file)


def uuid(category: str, full_name: str, identifier: str) -> str:
key = '{}-{}-{}'.format(category, full_name, identifier).lower().replace(' ', '~')
if key not in uuid_cache:
uuid_cache[key] = str(uuid4())
return uuid_cache[key]
uuid_cache = UuidCache('uuid_cache_axial_tht.csv')


def calculate_pad_hole_diameter(max_leg_diameter: float) -> float:
Expand Down Expand Up @@ -157,7 +147,7 @@ def generate_pkg(
)

def _uuid(identifier: str) -> str:
return uuid('pkg', pkg_identifier, identifier)
return uuid_cache.get('pkg', pkg_identifier, identifier)

uuid_pkg = _uuid('pkg')

Expand Down Expand Up @@ -759,7 +749,7 @@ def generate_3d(
assembly.save(out_path, fused=True)


if __name__ == '__main__':
def main() -> None:
if '--help' in sys.argv or '-h' in sys.argv:
print(f'Usage: {sys.argv[0]} [--3d]')
print()
Expand Down Expand Up @@ -1036,4 +1026,7 @@ def generate_3d(
generate_3d_models=generate_3d_models,
)

save_cache(uuid_cache_file, uuid_cache)

if __name__ == '__main__':
with uuid_cache:
main()
42 changes: 12 additions & 30 deletions generate_capacitor_radial_tht.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

import sys
from os import path
from uuid import uuid4

from typing import Any, Optional

from common import format_ipc_dimension, init_cache, now, save_cache
from common import UuidCache, format_ipc_dimension, now
from entities.common import (
Align,
Angle,
Expand Down Expand Up @@ -76,27 +75,7 @@
0.8: 1.0,
}

# Initialize UUID cache
uuid_cache_file = 'uuid_cache_capacitors_radial_tht.csv'
uuid_cache = init_cache(uuid_cache_file)


def uuid(category: str, full_name: str, identifier: str) -> str:
"""
Return a uuid for the specified element.

Params:
category:
For example 'cmp' or 'pkg'.
full_name:
For example "SOIC127P762X120-16".
identifier:
For example 'pad-1' or 'pin-13'.
"""
key = '{}-{}-{}'.format(category, full_name, identifier).lower().replace(' ', '~')
if key not in uuid_cache:
uuid_cache[key] = str(uuid4())
return uuid_cache[key]
uuid_cache = UuidCache('uuid_cache_capacitors_radial_tht.csv')


def get_variant(
Expand Down Expand Up @@ -130,7 +109,7 @@ def generate_pkg(
variant = get_variant(diameter, height, pitch, lead_width)

def _pkg_uuid(identifier: str) -> str:
return uuid('pkg', variant, identifier)
return uuid_cache.get('pkg', variant, identifier)

def _create_footprint(footprint_identifier: str, name: str) -> Footprint:
def _fpt_uuid(identifier: str) -> str:
Expand Down Expand Up @@ -456,7 +435,7 @@ def generate_dev(
variant = get_variant(diameter, height, pitch, lead_width)

def _uuid(identifier: str) -> str:
return uuid('dev', variant, identifier)
return uuid_cache.get('dev', variant, identifier)

device = Device(
uuid=_uuid('dev'),
Expand All @@ -477,17 +456,17 @@ def _uuid(identifier: str) -> str:
generated_by=GeneratedBy(''),
categories=[Category('c011cc6b-b762-498e-8494-d1994f3043cf')],
component_uuid=ComponentUUID('c54375c5-7149-4ded-95c5-7462f7301ee7'),
package_uuid=PackageUUID(uuid('pkg', variant, 'pkg')),
package_uuid=PackageUUID(uuid_cache.get('pkg', variant, 'pkg')),
)
device.add_pad(
ComponentPad(
pad_uuid=uuid('pkg', variant, 'pad-plus'),
pad_uuid=uuid_cache.get('pkg', variant, 'pad-plus'),
signal=SignalUUID('e010ecbb-6210-4da3-9270-ebd58656dbf0'),
)
)
device.add_pad(
ComponentPad(
pad_uuid=uuid('pkg', variant, 'pad-minus'),
pad_uuid=uuid_cache.get('pkg', variant, 'pad-minus'),
signal=SignalUUID('af3ffca8-0085-4edb-a775-fcb759f63411'),
)
)
Expand All @@ -500,7 +479,7 @@ def _uuid(identifier: str) -> str:
print('Wrote device {}'.format(name))


if __name__ == '__main__':
def main() -> None:
if '--help' in sys.argv or '-h' in sys.argv:
print(f'Usage: {sys.argv[0]} [--3d]')
print()
Expand Down Expand Up @@ -564,4 +543,7 @@ def _uuid(identifier: str) -> str:
create_date='2019-12-29T14:14:11Z',
)

save_cache(uuid_cache_file, uuid_cache)

if __name__ == '__main__':
with uuid_cache:
main()
Loading
Loading