Skip to content

Commit 4f5fb76

Browse files
complete SpiceLibrary
1 parent d7062e5 commit 4f5fb76

File tree

3 files changed

+130
-70
lines changed

3 files changed

+130
-70
lines changed

PySpice/Scripts/Library.py

Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,10 @@
2222

2323
from pathlib import Path
2424
import argparse
25-
import os
2625

2726
####################################################################################################
2827

29-
import PySpice.Logging.Logging as Logging
28+
from PySpice.Logging import Logging
3029
logger = Logging.setup_logging()
3130

3231
####################################################################################################
@@ -36,45 +35,61 @@
3635
####################################################################################################
3736

3837
def main() -> None:
39-
4038
parser = argparse.ArgumentParser(description='Manage Spice library')
41-
42-
parser.add_argument('library_path', metavar='LibraryPath', type=str,
43-
help='Spice library root path')
44-
45-
parser.add_argument('--scan',
46-
default=False, action='store_true',
47-
help='Scan library')
48-
49-
parser.add_argument('--delete-yaml',
50-
default=False, action='store_true',
51-
help='WARNING: Delete YAML Files')
52-
53-
parser.add_argument('--add-category',
54-
type=str,
55-
help='Add a category')
56-
57-
parser.add_argument('--category',
58-
type=str,
59-
default=None,
60-
help='specify the category')
61-
62-
parser.add_argument('--add-library',
63-
type=str,
64-
help='Add a library')
65-
66-
parser.add_argument('--show-categories',
67-
default=False, action='store_true',
68-
help='Show categories')
69-
39+
parser.add_argument(
40+
'-l',
41+
'--library_path',
42+
required=True,
43+
help='Spice library root path',
44+
)
45+
parser.add_argument(
46+
'--scan',
47+
default=False,
48+
action='store_true',
49+
help='Scan library',
50+
)
51+
parser.add_argument(
52+
'--delete-yaml',
53+
default=False,
54+
action='store_true',
55+
help='WARNING: Delete YAML Files',
56+
)
57+
parser.add_argument(
58+
'--add-category',
59+
type=str,
60+
help='Add a category',
61+
)
62+
parser.add_argument(
63+
'--category',
64+
type=str,
65+
default=None,
66+
help='specify the category',
67+
)
68+
parser.add_argument(
69+
'--add-library',
70+
type=str,
71+
help='Add a library',
72+
)
73+
parser.add_argument(
74+
'--show-categories',
75+
default=False,
76+
action='store_true',
77+
help='Show categories',
78+
)
79+
parser.add_argument(
80+
'--search',
81+
help='search',
82+
)
7083
args = parser.parse_args()
7184

7285
##############################################
7386

7487
library_path = Path(args.library_path).resolve()
7588
print(f"Library is {library_path}")
7689

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

7994
if args.delete_yaml:
8095
rc = input('Confirm deletion (y/n): ')
@@ -90,4 +105,11 @@ def main() -> None:
90105
if args.add_library:
91106
if args.category is None:
92107
print("A category is required")
93-
108+
raise NotImplementedError
109+
110+
if args.search:
111+
print()
112+
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}")

PySpice/Spice/Library/Library.py

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929
import re
3030

3131
from .SpiceInclude import SpiceInclude
32-
from PySpice.Spice.Parser import SpiceFile, ParseError, Subcircuit, Model
32+
from PySpice.Spice.Parser import Subcircuit, Model
3333
from PySpice.Tools import PathTools
3434

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

37+
NEWLINE = os.linesep
38+
3739
_module_logger = logging.getLogger(__name__)
3840

3941
####################################################################################################
@@ -68,18 +70,18 @@ class SpiceLibrary:
6870

6971
##############################################
7072

71-
def __init__(self, root_path: str | Path, scan: bool=True) -> None:
73+
def __init__(self, root_path: str | Path, scan: bool = True) -> None:
7274
self._path = PathTools.expand_path(root_path)
7375
if not self._path.exists():
74-
os.mkdir(self._path)
76+
self._path.mkdir(parents=True)
7577
self._logger.info(f"Created {self._path}")
76-
7778
self._subcircuits = {}
7879
self._models = {}
79-
8080
if scan:
8181
self.scan()
8282
self.save()
83+
else:
84+
self.load()
8385

8486
##############################################
8587

@@ -100,13 +102,25 @@ def __getstate__(self):
100102
##############################################
101103

102104
def __setstate__(self, state):
103-
self.__dict__.update(state)
105+
# self.__dict__.update(state)
106+
self._subcircuits = state['subcircuits']
107+
self._models = state['models']
104108

105109
##############################################
106110

107111
def save(self) -> None:
108112
with open(self.db_path, 'wb') as fh:
109-
pickle.dump(self.__getstate__(), fh)
113+
_ = self.__getstate__()
114+
pickle.dump(_, fh)
115+
116+
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")
110124

111125
##############################################
112126

@@ -119,19 +133,19 @@ def _category_path(self, category: str) -> Path:
119133
def add_category(self, category: str) -> None:
120134
path = self._category_path(category)
121135
if not path.exists():
122-
os.makedirs(path)
136+
path.mkdir(parents=True)
123137
self._logger.info(f"Created {path}")
124138
else:
125139
self._logger.info(f"category '{category}' already exists")
126140

127141
##############################################
128142

129-
def _list_categories(self, path: Path | str, level: int=0) -> str:
143+
def _list_categories(self, path: Path | str, level: int = 0) -> str:
130144
text = ''
131145
indent = ' '*4*level
132146
for entry in sorted(os.scandir(path), key=lambda entry: entry.name):
133147
if entry.is_dir():
134-
text += f'{indent}{entry.name}' + os.linesep
148+
text += f'{indent}{entry.name}' + NEWLINE
135149
text += self._list_categories(entry.path, level+1)
136150
return text
137151

@@ -150,21 +164,23 @@ def scan(self) -> None:
150164

151165
def _handle_library(self, path: Path) -> None:
152166
spice_include = SpiceInclude(path)
153-
self._models.update({_: path for _ in spice_include.models})
154-
self._subcircuits.update({_: path for _ in spice_include.subcircuits})
167+
self._models.update({_.name: path for _ in spice_include.models})
168+
self._subcircuits.update({_.name: path for _ in spice_include.subcircuits})
155169

156170
##############################################
157171

158172
def delete_yaml(self) -> None:
159173
for path in PathTools.walk(self._path):
160174
extension = path.suffix.lower()
161175
if extension == '.yaml':
162-
self._logger.info(f"{os.linesep}Delete {path}")
163-
os.unlink(path)
176+
self._logger.info(f"{NEWLINE}Delete {path}")
177+
path.unlink()
164178

165179
##############################################
166180

167181
def __getitem__(self, name: str) -> Subcircuit | Model:
182+
if not (self._subcircuits or self._models):
183+
self._logger.warning("Empty library")
168184
if name in self._subcircuits:
169185
return self._subcircuits[name]
170186
elif name in self._models:
@@ -199,10 +215,12 @@ def models(self) -> Iterator[Model]:
199215
# ##############################################
200216

201217
def search(self, regexp: str) -> dict[str, Subcircuit | Model]:
202-
""" Return dict of all models/subcircuits with names matching regex s. """
218+
""" Return dict of all models/subcircuits with names matching regex. """
203219
regexp = re.compile(regexp)
204220
matches = {}
205221
models_subcircuits = {**self._models, **self._subcircuits}
222+
if not models_subcircuits:
223+
self._logger.warning("Empty library")
206224
for name, _ in models_subcircuits.items():
207225
if regexp.search(name):
208226
matches[name] = _

0 commit comments

Comments
 (0)