use Self type

This commit is contained in:
Jan Petykiewicz 2023-02-23 13:37:34 -08:00 • committed by jan
commit 4482ede3a7
17 changed files with 142 additions and 205 deletions

View file

@ -1,4 +1,4 @@
from typing import TypeVar
from typing import Self
#from types import MappingProxyType
from abc import ABCMeta, abstractmethod
@ -9,10 +9,6 @@ from ..error import MasqueError
_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass
T = TypeVar('T', bound='Annotatable')
I = TypeVar('I', bound='AnnotatableImpl')
class Annotatable(metaclass=ABCMeta):
"""
Abstract class for all annotatable entities

View file

@ -1,11 +1,8 @@
from typing import TypeVar
from typing import Self
from abc import ABCMeta
import copy
T = TypeVar('T', bound='Copyable')
class Copyable(metaclass=ABCMeta):
"""
Abstract class which adds .copy() and .deepcopy()
@ -15,7 +12,7 @@ class Copyable(metaclass=ABCMeta):
'''
---- Non-abstract methods
'''
def copy(self: T) -> T:
def copy(self) -> Self:
"""
Return a shallow copy of the object.
@ -24,7 +21,7 @@ class Copyable(metaclass=ABCMeta):
"""
return copy.copy(self)
def deepcopy(self: T) -> T:
def deepcopy(self) -> Self:
"""
Return a deep copy of the object.

View file

@ -1,4 +1,4 @@
from typing import TypeVar
from typing import Self
from abc import ABCMeta, abstractmethod
from ..utils import layer_t
@ -7,10 +7,6 @@ from ..utils import layer_t
_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass
T = TypeVar('T', bound='Layerable')
I = TypeVar('I', bound='LayerableImpl')
class Layerable(metaclass=ABCMeta):
"""
Abstract class for all layerable entities
@ -36,7 +32,7 @@ class Layerable(metaclass=ABCMeta):
---- Methods
'''
@abstractmethod
def set_layer(self: T, layer: layer_t) -> T:
def set_layer(self, layer: layer_t) -> Self:
"""
Set the layer
@ -72,6 +68,6 @@ class LayerableImpl(Layerable, metaclass=ABCMeta):
'''
---- Non-abstract methods
'''
def set_layer(self: I, layer: layer_t) -> I:
def set_layer(self, layer: layer_t) -> Self:
self.layer = layer
return self

View file

@ -1,11 +1,7 @@
from typing import TypeVar
from typing import Self
from abc import ABCMeta, abstractmethod
T = TypeVar('T', bound='Mirrorable')
#I = TypeVar('I', bound='MirrorableImpl')
class Mirrorable(metaclass=ABCMeta):
"""
Abstract class for all mirrorable entities
@ -16,7 +12,7 @@ class Mirrorable(metaclass=ABCMeta):
---- Abstract methods
'''
@abstractmethod
def mirror(self: T, axis: int) -> T:
def mirror(self, axis: int) -> Self:
"""
Mirror the entity across an axis.
@ -28,7 +24,7 @@ class Mirrorable(metaclass=ABCMeta):
"""
pass
def mirror2d(self: T, axes: tuple[bool, bool]) -> T:
def mirror2d(self, axes: tuple[bool, bool]) -> Self:
"""
Optionally mirror the entity across both axes

View file

@ -1,6 +1,6 @@
# TODO top-level comment about how traits should set __slots__ = (), and how to use AutoSlots
from typing import TypeVar, Any
from typing import Self, Any
from abc import ABCMeta, abstractmethod
import numpy
@ -12,10 +12,6 @@ from ..error import MasqueError
_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass
T = TypeVar('T', bound='Positionable')
I = TypeVar('I', bound='PositionableImpl')
class Positionable(metaclass=ABCMeta):
"""
Abstract class for all positionable entities
@ -39,7 +35,7 @@ class Positionable(metaclass=ABCMeta):
pass
@abstractmethod
def set_offset(self: T, offset: ArrayLike) -> T:
def set_offset(self, offset: ArrayLike) -> Self:
"""
Set the offset
@ -52,7 +48,7 @@ class Positionable(metaclass=ABCMeta):
pass
@abstractmethod
def translate(self: T, offset: ArrayLike) -> T:
def translate(self, offset: ArrayLike) -> Self:
"""
Translate the entity by the given offset
@ -116,10 +112,10 @@ class PositionableImpl(Positionable, metaclass=ABCMeta):
'''
---- Methods
'''
def set_offset(self: I, offset: ArrayLike) -> I:
def set_offset(self, offset: ArrayLike) -> Self:
self.offset = offset
return self
def translate(self: I, offset: ArrayLike) -> I:
def translate(self, offset: ArrayLike) -> Self:
self._offset += offset # type: ignore # NDArray += ArrayLike should be fine??
return self

View file

@ -1,4 +1,4 @@
from typing import TypeVar, TYPE_CHECKING
from typing import Self, TYPE_CHECKING
from abc import ABCMeta, abstractmethod
from ..error import MasqueError
@ -11,10 +11,6 @@ if TYPE_CHECKING:
from ..repetition import Repetition
T = TypeVar('T', bound='Repeatable')
I = TypeVar('I', bound='RepeatableImpl')
class Repeatable(metaclass=ABCMeta):
"""
Abstract class for all repeatable entities
@ -41,7 +37,7 @@ class Repeatable(metaclass=ABCMeta):
---- Methods
'''
@abstractmethod
def set_repetition(self: T, repetition: 'Repetition' | None) -> T:
def set_repetition(self, repetition: 'Repetition' | None) -> Self:
"""
Set the repetition
@ -80,6 +76,6 @@ class RepeatableImpl(Repeatable, metaclass=ABCMeta):
'''
---- Non-abstract methods
'''
def set_repetition(self: I, repetition: 'Repetition' | None) -> I:
def set_repetition(self, repetition: 'Repetition' | None) -> Self:
self.repetition = repetition
return self

View file

@ -1,4 +1,4 @@
from typing import TypeVar, cast, Any
from typing import Self, cast, Any
from abc import ABCMeta, abstractmethod
import numpy
@ -13,12 +13,6 @@ from ..utils import rotation_matrix_2d
_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass
T = TypeVar('T', bound='Rotatable')
I = TypeVar('I', bound='RotatableImpl')
P = TypeVar('P', bound='Pivotable')
J = TypeVar('J', bound='PivotableImpl')
class Rotatable(metaclass=ABCMeta):
"""
Abstract class for all rotatable entities
@ -29,7 +23,7 @@ class Rotatable(metaclass=ABCMeta):
---- Abstract methods
'''
@abstractmethod
def rotate(self: T, val: float) -> T:
def rotate(self, val: float) -> Self:
"""
Rotate the shape around its origin (0, 0), ignoring its offset.
@ -68,11 +62,11 @@ class RotatableImpl(Rotatable, metaclass=ABCMeta):
'''
---- Methods
'''
def rotate(self: I, rotation: float) -> I:
def rotate(self, rotation: float) -> Self:
self.rotation += rotation
return self
def set_rotation(self: I, rotation: float) -> I:
def set_rotation(self, rotation: float) -> Self:
"""
Set the rotation to a value
@ -94,7 +88,7 @@ class Pivotable(metaclass=ABCMeta):
__slots__ = ()
@abstractmethod
def rotate_around(self: P, pivot: ArrayLike, rotation: float) -> P:
def rotate_around(self, pivot: ArrayLike, rotation: float) -> Self:
"""
Rotate the object around a point.
@ -117,7 +111,7 @@ class PivotableImpl(Pivotable, metaclass=ABCMeta):
offset: Any # TODO see if we can get around defining `offset` in PivotableImpl
""" `[x_offset, y_offset]` """
def rotate_around(self: J, pivot: ArrayLike, rotation: float) -> J:
def rotate_around(self, pivot: ArrayLike, rotation: float) -> Self:
pivot = numpy.array(pivot, dtype=float)
cast(Positionable, self).translate(-pivot)
cast(Rotatable, self).rotate(rotation)

View file

@ -1,4 +1,4 @@
from typing import TypeVar
from typing import Self
from abc import ABCMeta, abstractmethod
from ..error import MasqueError
@ -8,10 +8,6 @@ from ..utils import is_scalar
_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass
T = TypeVar('T', bound='Scalable')
I = TypeVar('I', bound='ScalableImpl')
class Scalable(metaclass=ABCMeta):
"""
Abstract class for all scalable entities
@ -22,7 +18,7 @@ class Scalable(metaclass=ABCMeta):
---- Abstract methods
'''
@abstractmethod
def scale_by(self: T, c: float) -> T:
def scale_by(self, c: float) -> Self:
"""
Scale the entity by a factor
@ -62,11 +58,11 @@ class ScalableImpl(Scalable, metaclass=ABCMeta):
'''
---- Methods
'''
def scale_by(self: I, c: float) -> I:
def scale_by(self, c: float) -> Self:
self.scale *= c
return self
def set_scale(self: I, scale: float) -> I:
def set_scale(self, scale: float) -> Self:
"""
Set the sclae to a value