Improve type annotations based on mypy errors

This commit is contained in:
Jan Petykiewicz 2020-05-11 19:09:35 -07:00
commit 157df47884
13 changed files with 151 additions and 117 deletions

View file

@ -1,4 +1,4 @@
from typing import List, Tuple, Dict
from typing import List, Tuple, Dict, Optional, Sequence
import copy
import math
import numpy
@ -32,10 +32,10 @@ class Arc(Shape):
_width: float
""" Width of the arc """
poly_num_points: int
poly_num_points: Optional[int]
""" Sets the default number of points for `.polygonize()` """
poly_max_arclen: float
poly_max_arclen: Optional[float]
""" Sets the default max segement length for `.polygonize()` """
# radius properties
@ -77,7 +77,7 @@ class Arc(Shape):
# arc start/stop angle properties
@property
def angles(self) -> vector2:
def angles(self) -> numpy.ndarray: #ndarray[float]
"""
Return the start and stop angles `[a_start, a_stop]`.
Angles are measured from x-axis after rotation
@ -150,11 +150,11 @@ class Arc(Shape):
radii: vector2,
angles: vector2,
width: float,
poly_num_points: int = DEFAULT_POLY_NUM_POINTS,
poly_max_arclen: float = None,
poly_num_points: Optional[int] = DEFAULT_POLY_NUM_POINTS,
poly_max_arclen: Optional[float] = None,
offset: vector2 = (0.0, 0.0),
rotation: float = 0,
mirrored: Tuple[bool] = (False, False),
mirrored: Sequence[bool] = (False, False),
layer: layer_t = 0,
dose: float = 1.0,
locked: bool = False):
@ -182,8 +182,8 @@ class Arc(Shape):
return new
def to_polygons(self,
poly_num_points: int = None,
poly_max_arclen: float = None,
poly_num_points: Optional[int] = None,
poly_max_arclen: Optional[float] = None,
) -> List[Polygon]:
if poly_num_points is None:
poly_num_points = self.poly_num_points

View file

@ -1,4 +1,4 @@
from typing import List, Dict
from typing import List, Dict, Optional
import copy
import numpy
from numpy import pi
@ -16,10 +16,10 @@ class Circle(Shape):
_radius: float
""" Circle radius """
poly_num_points: int
poly_num_points: Optional[int]
""" Sets the default number of points for `.polygonize()` """
poly_max_arclen: float
poly_max_arclen: Optional[float]
""" Sets the default max segement length for `.polygonize()` """
# radius property
@ -40,8 +40,8 @@ class Circle(Shape):
def __init__(self,
radius: float,
poly_num_points: int = DEFAULT_POLY_NUM_POINTS,
poly_max_arclen: float = None,
poly_num_points: Optional[int] = DEFAULT_POLY_NUM_POINTS,
poly_max_arclen: Optional[float] = None,
offset: vector2 = (0.0, 0.0),
layer: layer_t = 0,
dose: float = 1.0,
@ -64,8 +64,8 @@ class Circle(Shape):
return new
def to_polygons(self,
poly_num_points: int = None,
poly_max_arclen: float = None,
poly_num_points: Optional[int] = None,
poly_max_arclen: Optional[float] = None,
) -> List[Polygon]:
if poly_num_points is None:
poly_num_points = self.poly_num_points

View file

@ -1,4 +1,4 @@
from typing import List, Tuple, Dict
from typing import List, Tuple, Dict, Sequence, Optional
import copy
import math
import numpy
@ -22,10 +22,10 @@ class Ellipse(Shape):
_rotation: float
""" Angle from x-axis to first radius (ccw, radians) """
poly_num_points: int
poly_num_points: Optional[int]
""" Sets the default number of points for `.polygonize()` """
poly_max_arclen: float
poly_max_arclen: Optional[float]
""" Sets the default max segement length for `.polygonize()` """
# radius properties
@ -85,11 +85,11 @@ class Ellipse(Shape):
def __init__(self,
radii: vector2,
poly_num_points: int = DEFAULT_POLY_NUM_POINTS,
poly_max_arclen: float = None,
poly_num_points: Optional[int] = DEFAULT_POLY_NUM_POINTS,
poly_max_arclen: Optional[float] = None,
offset: vector2 = (0.0, 0.0),
rotation: float = 0,
mirrored: Tuple[bool] = (False, False),
mirrored: Sequence[bool] = (False, False),
layer: layer_t = 0,
dose: float = 1.0,
locked: bool = False):
@ -114,8 +114,8 @@ class Ellipse(Shape):
return new
def to_polygons(self,
poly_num_points: int = None,
poly_max_arclen: float = None,
poly_num_points: Optional[int] = None,
poly_max_arclen: Optional[float] = None,
) -> List[Polygon]:
if poly_num_points is None:
poly_num_points = self.poly_num_points

View file

@ -1,4 +1,4 @@
from typing import List, Tuple, Dict
from typing import List, Tuple, Dict, Optional, Sequence
import copy
from enum import Enum
import numpy
@ -28,8 +28,8 @@ class Path(Shape):
__slots__ = ('_vertices', '_width', '_cap', '_cap_extensions')
_vertices: numpy.ndarray
_width: float
_cap_extensions: numpy.ndarray or None
_cap: PathCap
_cap_extensions: Optional[numpy.ndarray]
Cap = PathCap
@ -69,7 +69,7 @@ class Path(Shape):
# cap_extensions property
@property
def cap_extensions(self) -> numpy.ndarray or None:
def cap_extensions(self) -> Optional[numpy.ndarray]:
"""
Path end-cap extension
@ -144,11 +144,11 @@ class Path(Shape):
cap_extensions: numpy.ndarray = None,
offset: vector2 = (0.0, 0.0),
rotation: float = 0,
mirrored: Tuple[bool] = (False, False),
mirrored: Sequence[bool] = (False, False),
layer: layer_t = 0,
dose: float = 1.0,
locked: bool = False,
) -> 'Path':
):
self.unlock()
self._cap_extensions = None # Since .cap setter might access it
@ -182,7 +182,7 @@ class Path(Shape):
cap_extensions = None,
offset: vector2 = (0.0, 0.0),
rotation: float = 0,
mirrored: Tuple[bool] = (False, False),
mirrored: Sequence[bool] = (False, False),
layer: layer_t = 0,
dose: float = 1.0,
) -> 'Path':

View file

@ -1,4 +1,4 @@
from typing import List, Tuple, Dict
from typing import List, Tuple, Dict, Optional, Sequence
import copy
import numpy
from numpy import pi
@ -71,7 +71,7 @@ class Polygon(Shape):
vertices: numpy.ndarray,
offset: vector2 = (0.0, 0.0),
rotation: float = 0.0,
mirrored: Tuple[bool] = (False, False),
mirrored: Sequence[bool] = (False, False),
layer: layer_t = 0,
dose: float = 1.0,
locked: bool = False,
@ -86,7 +86,7 @@ class Polygon(Shape):
[self.mirror(a) for a, do in enumerate(mirrored) if do]
self.locked = locked
def __deepcopy__(self, memo: Dict = None) -> 'Polygon':
def __deepcopy__(self, memo: Optional[Dict] = None) -> 'Polygon':
memo = {} if memo is None else memo
new = copy.copy(self).unlock()
new._offset = self._offset.copy()
@ -154,14 +154,14 @@ class Polygon(Shape):
return poly
@staticmethod
def rect(xmin: float = None,
xctr: float = None,
xmax: float = None,
lx: float = None,
ymin: float = None,
yctr: float = None,
ymax: float = None,
ly: float = None,
def rect(xmin: Optional[float] = None,
xctr: Optional[float] = None,
xmax: Optional[float] = None,
lx: Optional[float] = None,
ymin: Optional[float] = None,
yctr: Optional[float] = None,
ymax: Optional[float] = None,
ly: Optional[float] = None,
layer: layer_t = 0,
dose: float = 1.0,
) -> 'Polygon':
@ -188,11 +188,17 @@ class Polygon(Shape):
"""
if lx is None:
if xctr is None:
assert(xmin is not None)
assert(xmax is not None)
xctr = 0.5 * (xmax + xmin)
lx = xmax - xmin
elif xmax is None:
assert(xmin is not None)
assert(xctr is not None)
lx = 2 * (xctr - xmin)
elif xmin is None:
assert(xctr is not None)
assert(xmax is not None)
lx = 2 * (xmax - xctr)
else:
raise PatternError('Two of xmin, xctr, xmax, lx must be None!')
@ -200,19 +206,29 @@ class Polygon(Shape):
if xctr is not None:
pass
elif xmax is None:
assert(xmin is not None)
assert(lx is not None)
xctr = xmin + 0.5 * lx
elif xmin is None:
assert(xmax is not None)
assert(lx is not None)
xctr = xmax - 0.5 * lx
else:
raise PatternError('Two of xmin, xctr, xmax, lx must be None!')
if ly is None:
if yctr is None:
assert(ymin is not None)
assert(ymax is not None)
yctr = 0.5 * (ymax + ymin)
ly = ymax - ymin
elif ymax is None:
assert(ymin is not None)
assert(yctr is not None)
ly = 2 * (yctr - ymin)
elif ymin is None:
assert(yctr is not None)
assert(ymax is not None)
ly = 2 * (ymax - yctr)
else:
raise PatternError('Two of ymin, yctr, ymax, ly must be None!')
@ -220,8 +236,12 @@ class Polygon(Shape):
if yctr is not None:
pass
elif ymax is None:
assert(ymin is not None)
assert(ly is not None)
yctr = ymin + 0.5 * ly
elif ymin is None:
assert(ly is not None)
assert(ymax is not None)
yctr = ymax - 0.5 * ly
else:
raise PatternError('Two of ymin, yctr, ymax, ly must be None!')

View file

@ -1,4 +1,4 @@
from typing import List, Tuple, Callable
from typing import List, Tuple, Callable, TypeVar, Optional, TYPE_CHECKING
from abc import ABCMeta, abstractmethod
import copy
import numpy
@ -6,6 +6,8 @@ import numpy
from ..error import PatternError, PatternLockedError
from ..utils import is_scalar, rotation_matrix_2d, vector2, layer_t
if TYPE_CHECKING:
from . import Polygon
# Type definitions
@ -18,6 +20,9 @@ normalized_shape_tuple = Tuple[Tuple,
DEFAULT_POLY_NUM_POINTS = 24
T = TypeVar('T', bound='Shape')
class Shape(metaclass=ABCMeta):
"""
Abstract class specifying functions common to all shapes.
@ -53,7 +58,10 @@ class Shape(metaclass=ABCMeta):
# --- Abstract methods
@abstractmethod
def to_polygons(self, num_vertices: int, max_arclen: float) -> List['Polygon']:
def to_polygons(self,
num_vertices: Optional[int] = None,
max_arclen: Optional[float] = None,
) -> List['Polygon']:
"""
Returns a list of polygons which approximate the shape.
@ -77,7 +85,7 @@ class Shape(metaclass=ABCMeta):
pass
@abstractmethod
def rotate(self, theta: float) -> 'Shape':
def rotate(self: T, theta: float) -> T:
"""
Rotate the shape around its origin (0, 0), ignoring its offset.
@ -90,7 +98,7 @@ class Shape(metaclass=ABCMeta):
pass
@abstractmethod
def mirror(self, axis: int) -> 'Shape':
def mirror(self: T, axis: int) -> T:
"""
Mirror the shape across an axis.
@ -104,7 +112,7 @@ class Shape(metaclass=ABCMeta):
pass
@abstractmethod
def scale_by(self, c: float) -> 'Shape':
def scale_by(self: T, c: float) -> T:
"""
Scale the shape's size (eg. radius, for a circle) by a constant factor.
@ -117,7 +125,7 @@ class Shape(metaclass=ABCMeta):
pass
@abstractmethod
def normalized_form(self, norm_value: int) -> normalized_shape_tuple:
def normalized_form(self: T, norm_value: int) -> normalized_shape_tuple:
"""
Writes the shape in a standardized notation, with offset, scale, rotation, and dose
information separated out from the remaining values.
@ -187,7 +195,7 @@ class Shape(metaclass=ABCMeta):
self._dose = val
# ---- Non-abstract methods
def copy(self) -> 'Shape':
def copy(self: T) -> T:
"""
Returns a deep copy of the shape.
@ -196,7 +204,7 @@ class Shape(metaclass=ABCMeta):
"""
return copy.deepcopy(self)
def translate(self, offset: vector2) -> 'Shape':
def translate(self: T, offset: vector2) -> T:
"""
Translate the shape by the given offset
@ -209,7 +217,7 @@ class Shape(metaclass=ABCMeta):
self.offset += offset
return self
def rotate_around(self, pivot: vector2, rotation: float) -> 'Shape':
def rotate_around(self: T, pivot: vector2, rotation: float) -> T:
"""
Rotate the shape around a point.
@ -428,7 +436,7 @@ class Shape(metaclass=ABCMeta):
return manhattan_polygons
def lock(self) -> 'Shape':
def lock(self: T) -> T:
"""
Lock the Shape, disallowing further changes
@ -438,7 +446,7 @@ class Shape(metaclass=ABCMeta):
object.__setattr__(self, 'locked', True)
return self
def unlock(self) -> 'Shape':
def unlock(self: T) -> T:
"""
Unlock the Shape

View file

@ -1,4 +1,4 @@
from typing import List, Tuple, Dict
from typing import List, Tuple, Dict, Sequence, Optional, MutableSequence
import copy
import numpy
from numpy import pi, inf
@ -21,7 +21,7 @@ class Text(Shape):
_string: str
_height: float
_rotation: float
_mirrored: List[str]
_mirrored: numpy.ndarray #ndarray[bool]
font_path: str
# vertices property
@ -57,11 +57,11 @@ class Text(Shape):
# Mirrored property
@property
def mirrored(self) -> List[bool]:
def mirrored(self) -> numpy.ndarray: #ndarray[bool]
return self._mirrored
@mirrored.setter
def mirrored(self, val: List[bool]):
def mirrored(self, val: Sequence[bool]):
if is_scalar(val):
raise PatternError('Mirrored must be a 2-element list of booleans')
self._mirrored = numpy.ndarray(val, dtype=bool, copy=True)
@ -72,7 +72,7 @@ class Text(Shape):
font_path: str,
offset: vector2 = (0.0, 0.0),
rotation: float = 0.0,
mirrored: Tuple[bool] = (False, False),
mirrored: Tuple[bool, bool] = (False, False),
layer: layer_t = 0,
dose: float = 1.0,
locked: bool = False,
@ -98,11 +98,11 @@ class Text(Shape):
return new
def to_polygons(self,
poly_num_points: int = None, # unused
poly_max_arclen: float = None, # unused
poly_num_points: Optional[int] = None, # unused
poly_max_arclen: Optional[float] = None, # unused
) -> List[Polygon]:
all_polygons = []
total_advance = 0
total_advance = 0.0
for char in self.string:
raw_polys, advance = get_char_as_polygons(self.font_path, char)
@ -198,7 +198,7 @@ def get_char_as_polygons(font_path: str,
tags = outline.tags[start:end + 1]
tags.append(tags[0])
segments = []
segments: List[List[List[float]]] = []
for j, point in enumerate(points):
# If we already have a segment, add this point to it
if j > 0: