add support for annotations
and other fixes
This commit is contained in:
parent
5d83e0e5c0
commit
49a3b4e322
28 changed files with 400 additions and 133 deletions
|
|
@ -7,3 +7,4 @@ from .scalable import Scalable, ScalableImpl
|
|||
from .mirrorable import Mirrorable
|
||||
from .copyable import Copyable
|
||||
from .lockable import Lockable, LockableImpl
|
||||
from .annotatable import Annotatable, AnnotatableImpl
|
||||
|
|
|
|||
56
masque/traits/annotatable.py
Normal file
56
masque/traits/annotatable.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
from typing import TypeVar
|
||||
from types import MappingProxyType
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
|
||||
from ..utils import annotations_t
|
||||
from ..error import PatternError
|
||||
|
||||
|
||||
T = TypeVar('T', bound='Annotatable')
|
||||
I = TypeVar('I', bound='AnnotatableImpl')
|
||||
|
||||
|
||||
class Annotatable(metaclass=ABCMeta):
|
||||
"""
|
||||
Abstract class for all annotatable entities
|
||||
Annotations correspond to GDS/OASIS "properties"
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
'''
|
||||
---- Properties
|
||||
'''
|
||||
@property
|
||||
@abstractmethod
|
||||
def annotations(self) -> annotations_t:
|
||||
"""
|
||||
Dictionary mapping annotation names to values
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class AnnotatableImpl(Annotatable, metaclass=ABCMeta):
|
||||
"""
|
||||
Simple implementation of `Annotatable`.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
_annotations: annotations_t
|
||||
""" Dictionary storing annotation name/value pairs """
|
||||
|
||||
'''
|
||||
---- Non-abstract properties
|
||||
'''
|
||||
@property
|
||||
def annotations(self) -> annotations_t:
|
||||
# TODO: Find a way to make sure the subclass implements Lockable without dealing with diamond inheritance or this extra hasattr
|
||||
if hasattr(self, 'is_locked') and self.is_locked():
|
||||
return MappingProxyType(self._annotations)
|
||||
return self._annotations
|
||||
|
||||
@annotations.setter
|
||||
def annotations(self, annotations: annotations_t):
|
||||
if not isinstance(annotations, dict):
|
||||
raise PatternError(f'annotations expected dict, got {type(annotations)}')
|
||||
self._annotations = annotations
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
from typing import List, Tuple, Callable, TypeVar, Optional
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import numpy
|
||||
|
||||
from ..error import PatternError, PatternLockedError
|
||||
from ..utils import is_scalar
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from typing import List, Tuple, Callable, TypeVar, Optional
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import numpy
|
||||
|
||||
from ..error import PatternError, PatternLockedError
|
||||
from ..utils import layer_t
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from typing import List, Tuple, Callable, TypeVar, Optional
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import numpy
|
||||
|
||||
from ..error import PatternError, PatternLockedError
|
||||
|
||||
|
|
@ -19,6 +18,7 @@ class Lockable(metaclass=ABCMeta):
|
|||
'''
|
||||
---- Methods
|
||||
'''
|
||||
@abstractmethod
|
||||
def lock(self: T) -> T:
|
||||
"""
|
||||
Lock the object, disallowing further changes
|
||||
|
|
@ -28,6 +28,7 @@ class Lockable(metaclass=ABCMeta):
|
|||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def unlock(self: T) -> T:
|
||||
"""
|
||||
Unlock the object, reallowing changes
|
||||
|
|
@ -37,6 +38,32 @@ class Lockable(metaclass=ABCMeta):
|
|||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def is_locked(self) -> bool:
|
||||
"""
|
||||
Returns:
|
||||
True if the object is locked
|
||||
"""
|
||||
pass
|
||||
|
||||
def set_locked(self: T, locked: bool) -> T:
|
||||
"""
|
||||
Locks or unlocks based on the argument.
|
||||
No action if already in the requested state.
|
||||
|
||||
Args:
|
||||
locked: State to set.
|
||||
|
||||
Returns:
|
||||
self
|
||||
"""
|
||||
if locked != self.is_locked():
|
||||
if locked:
|
||||
self.lock()
|
||||
else:
|
||||
self.unlock()
|
||||
return self
|
||||
|
||||
|
||||
class LockableImpl(Lockable, metaclass=ABCMeta):
|
||||
"""
|
||||
|
|
@ -62,3 +89,6 @@ class LockableImpl(Lockable, metaclass=ABCMeta):
|
|||
def unlock(self: I) -> I:
|
||||
object.__setattr__(self, 'locked', False)
|
||||
return self
|
||||
|
||||
def is_locked(self) -> bool:
|
||||
return self.locked
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from typing import List, Tuple, Callable, TypeVar, Optional
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import numpy
|
||||
|
||||
from ..error import PatternError, PatternLockedError
|
||||
|
||||
|
||||
T = TypeVar('T', bound='Mirrorable')
|
||||
#I = TypeVar('I', bound='MirrorableImpl')
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
from typing import List, Tuple, Callable, TypeVar, Optional
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import numpy
|
||||
import numpy # type: ignore
|
||||
|
||||
from ..error import PatternError, PatternLockedError
|
||||
from ..utils import is_scalar, rotation_matrix_2d, vector2
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from typing import List, Tuple, Callable, TypeVar, Optional, TYPE_CHECKING
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import numpy
|
||||
|
||||
from ..error import PatternError, PatternLockedError
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from typing import List, Tuple, Callable, TypeVar, Optional
|
|||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
|
||||
import numpy
|
||||
import numpy # type: ignore
|
||||
from numpy import pi
|
||||
|
||||
from .positionable import Positionable
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from typing import List, Tuple, Callable, TypeVar, Optional
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import numpy
|
||||
|
||||
from ..error import PatternError, PatternLockedError
|
||||
from ..utils import is_scalar
|
||||
|
|
|
|||
Loading…
Reference in a new issue