Adding getting library+library version+cell from pathname.
diff --git a/scripts/python-skywater-pdk/skywater_pdk/base.py b/scripts/python-skywater-pdk/skywater_pdk/base.py
index 84ce182..08096a6 100644
--- a/scripts/python-skywater-pdk/skywater_pdk/base.py
+++ b/scripts/python-skywater-pdk/skywater_pdk/base.py
@@ -14,11 +14,140 @@
 from dataclasses import dataclass
 from dataclasses_json import dataclass_json
 from enum import Enum
-from typing import Optional
+from typing import Optional, Union, Tuple
 
 
-def parse_filename(pathname):
-    """Extract library and module name from pathname.
+LibraryOrCell = Union['Library', 'Cell']
+
+
+def parse_pathname(pathname):
+    """Extract library and module name for pathname.
+
+    Returns
+    -------
+    obj : Library or Cell
+        Library or Cell information parsed from filename
+    filename : str, optional
+        String containing any filename extracted.
+        String containing the file extension
+
+    >>> parse_pathname('skywater-pdk/libraries/sky130_fd_sc_hd/v0.0.1/cells/a2111o')
+    (Cell(name='a2111o', library=Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash=''))), None)
+
+    >>> parse_pathname('skywater-pdk/libraries/sky130_fd_sc_hd/v0.0.1/cells/a2111o/README.rst')
+    (Cell(name='a2111o', library=Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash=''))), 'README.rst')
+
+    >>> parse_pathname('skywater-pdk/libraries/sky130_fd_sc_hd/v0.0.1')
+    (Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash='')), None)
+
+    >>> parse_pathname('skywater-pdk/libraries/sky130_fd_sc_hd/v0.0.1/README.rst')
+    (Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash='')), 'README.rst')
+
+    >>> parse_pathname('libraries/sky130_fd_sc_hd/v0.0.1')
+    (Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash='')), None)
+
+    >>> parse_pathname('libraries/sky130_fd_sc_hd/v0.0.1/README.rst')
+    (Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash='')), 'README.rst')
+
+    >>> parse_pathname('sky130_fd_sc_hd/v0.0.1')
+    (Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash='')), None)
+
+    >>> parse_pathname('sky130_fd_sc_hd/v0.0.1/README.rst')
+    (Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash='')), 'README.rst')
+
+    >>> parse_pathname('sky130_fd_sc_hd/v0.0.1/RANDOM')
+    (Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=LibraryVersion(milestone=0, major=0, minor=1, commits=0, hash='')), 'RANDOM')
+
+    >>> parse_pathname('RANDOM') #doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    ValueError: ...
+
+    >>> parse_pathname('libraries/RANDOM/v0.0.1') #doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    ValueError: ...
+
+    >>> parse_pathname('libraries/skywater_fd_sc_hd/vA.B.C') #doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    ValueError: ...
+    """
+    if os.path.exists(pathname):
+        pathname = os.path.abspath(pathname)
+
+    pathbits = pathname.split(os.path.sep)
+    # Remove any files at the end of the path
+    filename = None
+    if '.' in pathbits[-1]:
+        if not pathbits[-1].startswith('v'):
+            filename = pathbits.pop(-1)
+
+    obj_type = None
+    obj_name = None
+
+    lib_name = None
+    lib_version = None
+
+    while len(pathbits) > 1:
+        n1 = pathbits[-1]
+        n2 = pathbits[-2]
+        if len(pathbits) > 2:
+            n3 = pathbits[-3]
+        else:
+            n3 = ''
+
+        # [..., 'cells', <cellname>]
+        # [..., 'models', <modname>]
+        if n2 in ('cells', 'models'):
+            obj_name = pathbits.pop(-1)
+            obj_type = pathbits.pop(-1)
+            continue
+        # [..., 'skywater-pdk', 'libraries', <library name>, <library version>]
+        elif n3 == "libraries":
+            lib_version = pathbits.pop(-1)
+            lib_name = pathbits.pop(-1)
+            assert pathbits.pop(-1) == 'libraries'
+        # [..., 'skywater-pdk', 'libraries', <library name>]
+        elif n2 == "libraries":
+            lib_name = pathbits.pop(-1)
+            assert pathbits.pop(-1) == 'libraries'
+        # [<library name>, <library version>]
+        elif n1.startswith('v'):
+            lib_version = pathbits.pop(-1)
+            lib_name = pathbits.pop(-1)
+        elif filename is None:
+            filename = pathbits.pop(-1)
+            continue
+        else:
+            raise ValueError('Unable to parse: {}'.format(pathname))
+        break
+
+    if not lib_name:
+        raise ValueError('Unable to parse: {}'.format(pathname))
+    lib = Library.parse(lib_name)
+    if lib_version:
+        lib.version = LibraryVersion.parse(lib_version)
+    if obj_name:
+        obj = Cell.parse(obj_name)
+        obj.library = lib
+        return obj, filename
+    else:
+        return lib, filename
+
+
+
+def parse_filename(pathname) -> Tuple[LibraryOrCell, Optional[str], Optional[str]]:
+    """Extract library and module name from filename.
+
+    Returns
+    -------
+    obj : Library or Cell
+        Library or Cell information parsed from filename
+    extra : str, optional
+        String containing any extra unparsed data (like corner information)
+    ext : str, optional
+        String containing the file extension
 
     >>> t = list(parse_filename('sky130_fd_io__top_ground_padonlyv2__tt_1p80V_3p30V_3p30V_25C.wrap.lib'))
     >>> t.pop(0)
@@ -52,7 +181,7 @@
 
     # Extract a version if it exists.
     dirbase, dirversion = os.path.split(dirname)
-    if dirbase.endswith('/cells'):
+    if dirbase.endswith('cells'):
         dirbase, dirversion = os.path.split(dirbase)
         assert dirversion == 'cells', (dirbase, dirversion)
         dirbase, dirversion = os.path.split(dirbase)