Skip to content

Commit a05f0f5

Browse files
improve spice library
1 parent fd89227 commit a05f0f5

File tree

7 files changed

+220
-74
lines changed

7 files changed

+220
-74
lines changed

PySpice/Scripts/Library.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
####################################################################################################
3232

33-
from PySpice.Spice.Library import SpiceLibrary
33+
from PySpice.Spice.Library import SpiceLibrary, Model, Subcircuit
3434

3535
####################################################################################################
3636

@@ -87,9 +87,7 @@ def main() -> None:
8787
library_path = Path(args.library_path).resolve()
8888
print(f"Library is {library_path}")
8989

90-
# scan = args.search is not None or args.scan
91-
scan = False
92-
spice_library = SpiceLibrary(library_path, scan=scan)
90+
spice_library = SpiceLibrary(library_path, scan=args.scan)
9391

9492
if args.delete_yaml:
9593
rc = input('Confirm deletion (y/n): ')
@@ -110,6 +108,18 @@ def main() -> None:
110108
if args.search:
111109
print()
112110
print(f'Results for "{args.search}":')
113-
for name, path in spice_library.search(args.search).items():
114-
path = path.relative_to(library_path)
115-
print(f" {name} {path}")
111+
# list() to don't mix logging and print
112+
for name, include in list(spice_library.search(args.search)):
113+
path = include.path.relative_to(library_path)
114+
print(' '*2 + f"{name} {path}")
115+
indent = ' '*4
116+
if include.description:
117+
print(f"{indent}Library: {include.description}")
118+
_ = include[name]
119+
is_model = isinstance(_, Model)
120+
if is_model:
121+
print(f"{indent}Model: {_.name}{_.description}")
122+
else:
123+
print(f"{indent}Subcircuit: {_.name}{_.description}")
124+
pins = ' '.join(_.pin_names)
125+
print(f"{indent}Pins: {pins}")

PySpice/Spice/Library/Library.py

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@
2121
####################################################################################################
2222

2323
from pathlib import Path
24-
from typing import Iterator
24+
from typing import Iterable, Iterator
2525

2626
import logging
2727
import os
2828
import pickle
2929
import re
3030

31-
from .SpiceInclude import SpiceInclude
3231
from PySpice.Spice.Parser import Subcircuit, Model
3332
from PySpice.Tools import PathTools
33+
from .SpiceInclude import SpiceInclude, is_yaml
3434

3535
####################################################################################################
3636

@@ -70,25 +70,38 @@ class SpiceLibrary:
7070

7171
##############################################
7272

73-
def __init__(self, root_path: str | Path, scan: bool = True) -> None:
73+
def __init__(self, root_path: str | Path, scan: bool = False) -> None:
7474
self._path = PathTools.expand_path(root_path)
7575
if not self._path.exists():
7676
self._path.mkdir(parents=True)
7777
self._logger.info(f"Created {self._path}")
7878
self._subcircuits = {}
7979
self._models = {}
80+
if not scan:
81+
if self.has_db_path:
82+
self.load()
83+
else:
84+
self._logger.info("Initialize library...")
85+
scan = True
8086
if scan:
8187
self.scan()
8288
self.save()
83-
else:
84-
self.load()
8589

8690
##############################################
8791

8892
@property
8993
def db_path(self) -> Path:
9094
return self._path.joinpath('db.pickle')
9195

96+
@property
97+
def has_db_path(self) -> bool:
98+
return self.db_path.exists()
99+
100+
##############################################
101+
102+
def __bool__(self) -> bool:
103+
return bool(self._subcircuits or self._models)
104+
92105
##############################################
93106

94107
def __getstate__(self):
@@ -114,13 +127,10 @@ def save(self) -> None:
114127
pickle.dump(_, fh)
115128

116129
def load(self) -> None:
117-
if self.db_path.exists():
118-
self._logger.info(f"Load {self.db_path}")
119-
with open(self.db_path, 'rb') as fh:
120-
_ = pickle.load(fh)
121-
self.__setstate__(_)
122-
else:
123-
self._logger.warning("uninitialised library")
130+
self._logger.info(f"Load {self.db_path}")
131+
with open(self.db_path, 'rb') as fh:
132+
_ = pickle.load(fh)
133+
self.__setstate__(_)
124134

125135
##############################################
126136

@@ -155,40 +165,43 @@ def list_categories(self) -> str:
155165
##############################################
156166

157167
def scan(self) -> None:
168+
self._logger.info(f"Scan {self._path}...")
158169
for path in PathTools.walk(self._path):
159-
extension = path.suffix.lower()
160-
if extension in self.EXTENSIONS:
170+
_ = path.suffix.lower()
171+
if _ in self.EXTENSIONS:
161172
self._handle_library(path)
162173

163174
##############################################
164175

165176
def _handle_library(self, path: Path) -> None:
166177
spice_include = SpiceInclude(path)
178+
# Fixme: check overwrite
167179
self._models.update({_.name: path for _ in spice_include.models})
168180
self._subcircuits.update({_.name: path for _ in spice_include.subcircuits})
169181

170182
##############################################
171183

172184
def delete_yaml(self) -> None:
173185
for path in PathTools.walk(self._path):
174-
extension = path.suffix.lower()
175-
if extension == '.yaml':
186+
if is_yaml(path):
176187
self._logger.info(f"{NEWLINE}Delete {path}")
177188
path.unlink()
178189

179190
##############################################
180191

181192
def __getitem__(self, name: str) -> Subcircuit | Model:
182-
if not (self._subcircuits or self._models):
193+
if not self:
183194
self._logger.warning("Empty library")
184195
if name in self._subcircuits:
185-
return self._subcircuits[name]
196+
path = self._subcircuits[name]
186197
elif name in self._models:
187-
return self._models[name]
198+
path = self._models[name]
188199
else:
189200
# print('Library {} not found in {}'.format(name, self._path))
190201
# self._logger.warn('Library {} not found in {}'.format(name, self._path))
191202
raise KeyError(name)
203+
# Fixme: lazy ???
204+
return SpiceInclude(path)[name]
192205

193206
##############################################
194207

@@ -214,14 +227,12 @@ def models(self) -> Iterator[Model]:
214227

215228
# ##############################################
216229

217-
def search(self, regexp: str) -> dict[str, Subcircuit | Model]:
230+
def search(self, regexp: str) -> Iterable[tuple[str, SpiceInclude]]:
218231
""" Return dict of all models/subcircuits with names matching regex. """
219232
regexp = re.compile(regexp)
220-
matches = {}
221233
models_subcircuits = {**self._models, **self._subcircuits}
222234
if not models_subcircuits:
223235
self._logger.warning("Empty library")
224236
for name, _ in models_subcircuits.items():
225237
if regexp.search(name):
226-
matches[name] = _
227-
return matches
238+
yield name, SpiceInclude(_)

0 commit comments

Comments
 (0)