Skip to content

Commit

Permalink
complete SpiceLibrary
Browse files Browse the repository at this point in the history
  • Loading branch information
FabriceSalvaire committed Jan 26, 2024
1 parent d7062e5 commit 4f5fb76
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 70 deletions.
90 changes: 56 additions & 34 deletions PySpice/Scripts/Library.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@

from pathlib import Path
import argparse
import os

####################################################################################################

import PySpice.Logging.Logging as Logging
from PySpice.Logging import Logging
logger = Logging.setup_logging()

####################################################################################################
Expand All @@ -36,45 +35,61 @@
####################################################################################################

def main() -> None:

parser = argparse.ArgumentParser(description='Manage Spice library')

parser.add_argument('library_path', metavar='LibraryPath', type=str,
help='Spice library root path')

parser.add_argument('--scan',
default=False, action='store_true',
help='Scan library')

parser.add_argument('--delete-yaml',
default=False, action='store_true',
help='WARNING: Delete YAML Files')

parser.add_argument('--add-category',
type=str,
help='Add a category')

parser.add_argument('--category',
type=str,
default=None,
help='specify the category')

parser.add_argument('--add-library',
type=str,
help='Add a library')

parser.add_argument('--show-categories',
default=False, action='store_true',
help='Show categories')

parser.add_argument(
'-l',
'--library_path',
required=True,
help='Spice library root path',
)
parser.add_argument(
'--scan',
default=False,
action='store_true',
help='Scan library',
)
parser.add_argument(
'--delete-yaml',
default=False,
action='store_true',
help='WARNING: Delete YAML Files',
)
parser.add_argument(
'--add-category',
type=str,
help='Add a category',
)
parser.add_argument(
'--category',
type=str,
default=None,
help='specify the category',
)
parser.add_argument(
'--add-library',
type=str,
help='Add a library',
)
parser.add_argument(
'--show-categories',
default=False,
action='store_true',
help='Show categories',
)
parser.add_argument(
'--search',
help='search',
)
args = parser.parse_args()

##############################################

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

spice_library = SpiceLibrary(library_path, scan=args.scan)
# scan = args.search is not None or args.scan
scan = False
spice_library = SpiceLibrary(library_path, scan=scan)

if args.delete_yaml:
rc = input('Confirm deletion (y/n): ')
Expand All @@ -90,4 +105,11 @@ def main() -> None:
if args.add_library:
if args.category is None:
print("A category is required")

raise NotImplementedError

if args.search:
print()
print(f'Results for "{args.search}":')
for name, path in spice_library.search(args.search).items():
path = path.relative_to(library_path)
print(f" {name} {path}")
48 changes: 33 additions & 15 deletions PySpice/Spice/Library/Library.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
import re

from .SpiceInclude import SpiceInclude
from PySpice.Spice.Parser import SpiceFile, ParseError, Subcircuit, Model
from PySpice.Spice.Parser import Subcircuit, Model
from PySpice.Tools import PathTools

####################################################################################################

NEWLINE = os.linesep

_module_logger = logging.getLogger(__name__)

####################################################################################################
Expand Down Expand Up @@ -68,18 +70,18 @@ class SpiceLibrary:

##############################################

def __init__(self, root_path: str | Path, scan: bool=True) -> None:
def __init__(self, root_path: str | Path, scan: bool = True) -> None:
self._path = PathTools.expand_path(root_path)
if not self._path.exists():
os.mkdir(self._path)
self._path.mkdir(parents=True)
self._logger.info(f"Created {self._path}")

self._subcircuits = {}
self._models = {}

if scan:
self.scan()
self.save()
else:
self.load()

##############################################

Expand All @@ -100,13 +102,25 @@ def __getstate__(self):
##############################################

def __setstate__(self, state):
self.__dict__.update(state)
# self.__dict__.update(state)
self._subcircuits = state['subcircuits']
self._models = state['models']

##############################################

def save(self) -> None:
with open(self.db_path, 'wb') as fh:
pickle.dump(self.__getstate__(), fh)
_ = self.__getstate__()
pickle.dump(_, fh)

def load(self) -> None:
if self.db_path.exists():
self._logger.info(f"Load {self.db_path}")
with open(self.db_path, 'rb') as fh:
_ = pickle.load(fh)
self.__setstate__(_)
else:
self._logger.warning("uninitialised library")

##############################################

Expand All @@ -119,19 +133,19 @@ def _category_path(self, category: str) -> Path:
def add_category(self, category: str) -> None:
path = self._category_path(category)
if not path.exists():
os.makedirs(path)
path.mkdir(parents=True)
self._logger.info(f"Created {path}")
else:
self._logger.info(f"category '{category}' already exists")

##############################################

def _list_categories(self, path: Path | str, level: int=0) -> str:
def _list_categories(self, path: Path | str, level: int = 0) -> str:
text = ''
indent = ' '*4*level
for entry in sorted(os.scandir(path), key=lambda entry: entry.name):
if entry.is_dir():
text += f'{indent}{entry.name}' + os.linesep
text += f'{indent}{entry.name}' + NEWLINE
text += self._list_categories(entry.path, level+1)
return text

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

def _handle_library(self, path: Path) -> None:
spice_include = SpiceInclude(path)
self._models.update({_: path for _ in spice_include.models})
self._subcircuits.update({_: path for _ in spice_include.subcircuits})
self._models.update({_.name: path for _ in spice_include.models})
self._subcircuits.update({_.name: path for _ in spice_include.subcircuits})

##############################################

def delete_yaml(self) -> None:
for path in PathTools.walk(self._path):
extension = path.suffix.lower()
if extension == '.yaml':
self._logger.info(f"{os.linesep}Delete {path}")
os.unlink(path)
self._logger.info(f"{NEWLINE}Delete {path}")
path.unlink()

##############################################

def __getitem__(self, name: str) -> Subcircuit | Model:
if not (self._subcircuits or self._models):
self._logger.warning("Empty library")
if name in self._subcircuits:
return self._subcircuits[name]
elif name in self._models:
Expand Down Expand Up @@ -199,10 +215,12 @@ def models(self) -> Iterator[Model]:
# ##############################################

def search(self, regexp: str) -> dict[str, Subcircuit | Model]:
""" Return dict of all models/subcircuits with names matching regex s. """
""" Return dict of all models/subcircuits with names matching regex. """
regexp = re.compile(regexp)
matches = {}
models_subcircuits = {**self._models, **self._subcircuits}
if not models_subcircuits:
self._logger.warning("Empty library")
for name, _ in models_subcircuits.items():
if regexp.search(name):
matches[name] = _
Expand Down
Loading

0 comments on commit 4f5fb76

Please sign in to comment.