Source code for jLM.BaseTypes

# 
# University of Illinois Open Source License
# Copyright 2016-2018 Luthey-Schulten Group,
# All rights reserved.
# 
# Developed by: Luthey-Schulten Group
#                           University of Illinois at Urbana-Champaign
#                           http://www.scs.uiuc.edu/~schulten
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the Software), to deal with 
# the Software without restriction, including without limitation the rights to 
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
# of the Software, and to permit persons to whom the Software is furnished to 
# do so, subject to the following conditions:
# 
# - Redistributions of source code must retain the above copyright notice, 
# this list of conditions and the following disclaimers.
# 
# - Redistributions in binary form must reproduce the above copyright notice, 
# this list of conditions and the following disclaimers in the documentation 
# and/or other materials provided with the distribution.
# 
# - Neither the names of the Luthey-Schulten Group, University of Illinois at
# Urbana-Champaign, nor the names of its contributors may be used to endorse or
# promote products derived from this Software without specific prior written
# permission.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
# THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
# OTHER DEALINGS WITH THE SOFTWARE.
# 
# Author(s): Tyler M. Earnest
# 

"""Simulation object base class and collections"""

import re
from . import Template

from abc import ABCMeta, abstractmethod

def _goodName(s):
    return (len(s) == len(s.encode()) and       # ensure no weird unicode stuff
            not any(x.isspace() for x in s) and # no whitespace
            ',' not in s)                       # comma used as a delimiter in HDF5

[docs] class Namespace: """This function simply creates and returns a new Namespace object wrapping the current SimObjs container. The main purpose is to provide a more user-friendly interface for accessing simulation objects through tab completion. """ def __init__(self, sos): """Convienence class for TAB completing simulation objects Args: sos (:py:class:`~jLM.BaseTypes.SimObjs`): Object collection """ self._simobj = sos def __getattr__(self, name): obj = self._simobj._obj.get(name) if obj is None: raise AttributeError("Unknown object: {}".format(name)) else: return obj def __dir__(self): return [o.name for o in self._simobj] def _repr_html_(self): return Template.j2render("objContainer.html", dict(title=self._simobj.__repr__(), annotationCol=any(o.annotation is not None for o in self._simobj), texStr=any(o._texstr is not None for o in self._simobj), objs=[dict(id=o.idx, html=o._repr_html_(), annotation=o.annotation, tex=o._texstr) for o in self._simobj]))
[docs] class SimObjs: """Container to manage simulation data types"""
[docs] def getAutoNamespace(self): """Get :py:class:`~jLM.BaseTypes.Namespace` object.""" return Namespace(self)
[docs] def matchRegex(self, regex): """Generator returning matches to regular expression Args: regex (str): Regular expression matching the name attribute of contained objects Returns: generator: Generator of :py:class:`~jLM.Types.SimObj` """ for v in sorted(self._obj.values(), key=lambda x: -x.idx): if re.match(regex, v.name): yield v
def __getitem__(self, what): """Get object by name or idx integer""" try: return self._obj[what] except KeyError: return self._id2obj[what] def __len__(self): return len(self._obj) def __iter__(self): return (self[i+self._idbase] for i in range(len(self._obj))) def __init__(self, sim, cls, idbase=0): self._cls = cls # Class type for the objects being stored self._sim = sim # Reference to simulation instance self._idbase = idbase # Starting index for object IDs self._obj = dict() self._id2name = dict() self._id2obj = dict() self._frozen = False
[docs] def freeze(self): """Do not create new objects from failed lookups""" self._frozen = True
[docs] def unfreeze(self): """Create new objects from failed lookups""" self._frozen = False
[docs] def is_defined(self, *args, **kwargs): """Check if `get` would create a new object Args: *args: Arguments to constructor Keyword Args: **kwargs: Keyword arguments to constructor Returns: bool: True if would create new object. """ name = self._cls._unique_id(*args, **kwargs) return name in self._obj
[docs] def get(self, *args, **kwargs): """Return a simulation object, create it if it does not exist Args: *args: Arguments to constructor Keyword Args: **kwargs: Keyword arguments to constructor Returns: :py:class:`~jLM.BaseTypes.SimObj`: Object """ name = self._cls._unique_id(*args, **kwargs) try: return self._obj[name] except KeyError: if not self._frozen: idx = len(self._obj)+self._idbase obj = self._cls(self._sim, idx, *args, **kwargs) self._obj[name] = obj self._id2name[obj.idx] = obj.name self._id2obj[obj.idx] = obj return obj else: raise
[docs] class SimObj(metaclass=ABCMeta): """Base class to simulation objects""" @classmethod @abstractmethod def _unique_id(cls, *args, **kwargs): pass def _TeXMath(self): if hasattr(self, '_texstr') and self._texstr is not None: return self._texstr else: return self._TeX() def __init__(self, sim, idx, *args, **kwargs): if 'annotation' in kwargs: self.annotation = kwargs['annotation'] del kwargs['annotation'] else: self.annotation = None name = self._unique_id(*args, **kwargs) if 'texRepr' in kwargs: self._texstr = kwargs['texRepr'] del kwargs['texRepr'] else: self._texstr = None if not _goodName(name): raise ValueError("Invalid name: "+name) self.name = name self._sim = sim self.idx = idx self._setup(*args, **kwargs) self._staticAttrs = set(dir(self)) def _dynamicAttrs(self): return [ x for x in set(dir(self)) - self._staticAttrs if x[0] != "_" ] def _setup(self, *args, **kwargs): pass def __lt__(lhs,rhs): return lhs.idx < rhs.idx def _repr_html_(self): try: return self._html() except AttributeError: return "$$"+self._TeXMath()+"$$"