-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Complete type hints #121
Complete type hints #121
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,10 +32,11 @@ | |
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
############################################################################# | ||
|
||
from __future__ import annotations | ||
|
||
from collections.abc import MutableSequence, Sequence | ||
from functools import cached_property | ||
import math | ||
from typing import Optional | ||
import warnings | ||
|
||
from attrs import astuple, define, field | ||
|
||
|
@@ -59,7 +60,7 @@ class UndefinedRotationError(AffineError): | |
"""The rotation angle could not be computed for this transform.""" | ||
|
||
|
||
def cos_sin_deg(deg: float): | ||
def cos_sin_deg(deg: float) -> tuple[float, float]: | ||
"""Return the cosine and sin for the given angle in degrees. | ||
|
||
With special-case handling of multiples of 90 for perfect right | ||
|
@@ -83,19 +84,13 @@ class Affine: | |
Parameters | ||
---------- | ||
a, b, c, d, e, f, [g, h, i] : float | ||
Coefficients of the 3 x 3 augmented affine transformation matrix. | ||
|
||
| x' | | a b c | | x | | ||
| y' | = | d e f | | y | | ||
| 1 | | 0 0 1 | | 1 | | ||
|
||
`a`, `b`, and `c` are the elements of the first row of the | ||
matrix. `d`, `e`, and `f` are the elements of the second row. | ||
Coefficients of the 3 x 3 augmented affine transformation | ||
matrix. | ||
|
||
Attributes | ||
---------- | ||
a, b, c, d, e, f, g, h, i : float | ||
The coefficients of the 3 x 3 augmented affine transformation | ||
Coefficients of the 3 x 3 augmented affine transformation | ||
matrix:: | ||
|
||
| x' | | a b c | | x | | ||
|
@@ -159,7 +154,9 @@ def _check_i(self, attribute, value): | |
raise ValueError("i must be equal to 1.0") | ||
|
||
@classmethod | ||
def from_gdal(cls, c: float, a: float, b: float, f: float, d: float, e: float): | ||
def from_gdal( | ||
cls, c: float, a: float, b: float, f: float, d: float, e: float | ||
) -> Affine: | ||
"""Use same coefficient order as GDAL's GetGeoTransform(). | ||
|
||
Parameters | ||
|
@@ -174,7 +171,7 @@ def from_gdal(cls, c: float, a: float, b: float, f: float, d: float, e: float): | |
return cls(a, b, c, d, e, f) | ||
|
||
@classmethod | ||
def identity(cls): | ||
def identity(cls) -> Affine: | ||
"""Return the identity transform. | ||
|
||
Returns | ||
|
@@ -184,7 +181,7 @@ def identity(cls): | |
return identity | ||
|
||
@classmethod | ||
def translation(cls, xoff: float, yoff: float): | ||
def translation(cls, xoff: float, yoff: float) -> Affine: | ||
"""Create a translation transform from an offset vector. | ||
|
||
Parameters | ||
|
@@ -199,7 +196,7 @@ def translation(cls, xoff: float, yoff: float): | |
return cls(1.0, 0.0, xoff, 0.0, 1.0, yoff) | ||
|
||
@classmethod | ||
def scale(cls, *scaling): | ||
def scale(cls, *scaling: float) -> Affine: | ||
"""Create a scaling transform from a scalar or vector. | ||
|
||
Parameters | ||
|
@@ -214,13 +211,14 @@ def scale(cls, *scaling): | |
Affine | ||
""" | ||
if len(scaling) == 1: | ||
sx = sy = float(scaling[0]) | ||
sx = scaling[0] | ||
sy = sx | ||
else: | ||
sx, sy = scaling | ||
return cls(sx, 0.0, 0.0, 0.0, sy, 0.0) | ||
|
||
@classmethod | ||
def shear(cls, x_angle: float = 0, y_angle: float = 0): | ||
def shear(cls, x_angle: float = 0.0, y_angle: float = 0.0) -> Affine: | ||
"""Create a shear transform along one or both axes. | ||
|
||
Parameters | ||
|
@@ -237,7 +235,7 @@ def shear(cls, x_angle: float = 0, y_angle: float = 0): | |
return cls(1.0, mx, 0.0, my, 1.0, 0.0) | ||
|
||
@classmethod | ||
def rotation(cls, angle: float, pivot=None): | ||
def rotation(cls, angle: float, pivot: Sequence[float] | None = None) -> Affine: | ||
"""Create a rotation transform at the specified angle. | ||
|
||
Parameters | ||
|
@@ -264,7 +262,7 @@ def rotation(cls, angle: float, pivot=None): | |
# fmt: on | ||
|
||
@classmethod | ||
def permutation(cls, *scaling): | ||
def permutation(cls, *scaling: float) -> Affine: | ||
"""Create the permutation transform. | ||
|
||
For 2x2 matrices, there is only one permutation matrix that is | ||
|
@@ -281,7 +279,7 @@ def permutation(cls, *scaling): | |
""" | ||
return cls(0.0, 1.0, 0.0, 1.0, 0.0, 0.0) | ||
|
||
def __array__(self, dtype=None, copy=None): | ||
def __array__(self, dtype=None, copy: bool | None = None): | ||
"""Get affine matrix as a 3x3 NumPy array. | ||
|
||
Parameters | ||
|
@@ -322,7 +320,7 @@ def __repr__(self) -> str: | |
f" {self.d!r}, {self.e!r}, {self.f!r})" | ||
) | ||
|
||
def to_gdal(self): | ||
def to_gdal(self) -> tuple[float, float, float, float, float, float]: | ||
"""Return same coefficient order expected by GDAL's SetGeoTransform(). | ||
|
||
Returns | ||
|
@@ -332,7 +330,7 @@ def to_gdal(self): | |
""" | ||
return (self.c, self.a, self.b, self.f, self.d, self.e) | ||
|
||
def to_shapely(self): | ||
def to_shapely(self) -> tuple[float, float, float, float, float, float]: | ||
"""Return affine transformation parameters for shapely's affinity module. | ||
|
||
Returns | ||
|
@@ -366,7 +364,7 @@ def determinant(self) -> float: | |
return self.a * self.e - self.b * self.d | ||
|
||
@property | ||
def _scaling(self): | ||
def _scaling(self) -> tuple[float, float]: | ||
"""The absolute scaling factors of the transformation. | ||
|
||
This tuple represents the absolute value of the scaling factors of the | ||
|
@@ -493,7 +491,9 @@ def is_proper(self) -> bool: | |
return self.determinant > 0.0 | ||
|
||
@property | ||
def column_vectors(self): | ||
def column_vectors( | ||
self, | ||
) -> tuple[tuple[float, float], tuple[float, float], tuple[float, float]]: | ||
"""The values of the transform as three 2D column vectors. | ||
|
||
Returns | ||
|
@@ -503,7 +503,7 @@ def column_vectors(self): | |
""" | ||
return (self.a, self.d), (self.b, self.e), (self.c, self.f) | ||
|
||
def almost_equals(self, other, precision: Optional[float] = None) -> bool: | ||
def almost_equals(self, other: Affine, precision: float | None = None) -> bool: | ||
"""Compare transforms for approximate equality. | ||
|
||
Parameters | ||
|
@@ -523,7 +523,7 @@ def almost_equals(self, other, precision: Optional[float] = None) -> bool: | |
return all(abs(sv - ov) < precision for sv, ov in zip(self, other)) | ||
|
||
@cached_property | ||
def _astuple(self): | ||
def _astuple(self) -> tuple[float]: | ||
return astuple(self) | ||
|
||
def __getitem__(self, index): | ||
|
@@ -582,41 +582,12 @@ def __mul__(self, other): | |
return NotImplemented | ||
|
||
def __rmul__(self, other): | ||
"""Right hand multiplication. | ||
|
||
.. deprecated:: 2.3.0 | ||
Right multiplication will be prohibited in version 3.0. This method | ||
will raise AffineError. | ||
|
||
Parameters | ||
---------- | ||
other : Affine or iterable of (vx, vy) | ||
|
||
Returns | ||
------- | ||
tuple of two floats | ||
|
||
Notes | ||
----- | ||
We should not be called if other is an affine instance This is | ||
just a guarantee, since we would potentially return the wrong | ||
answer in that case. | ||
""" | ||
warnings.warn( | ||
"Right multiplication will be prohibited in version 3.0", | ||
DeprecationWarning, | ||
stacklevel=2, | ||
) | ||
assert not isinstance(other, Affine) | ||
return self.__mul__(other) | ||
return NotImplemented | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also not related to type hinting: removal of the right multiplication implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also note: I'm not providing type hints for dunder methods. These are specified by the Python language. |
||
|
||
def __imul__(self, other): | ||
"""Provide wrapper for `__mul__`, however `other` is not modified in-place.""" | ||
if isinstance(other, (Affine, tuple)): | ||
return self.__mul__(other) | ||
return NotImplemented | ||
|
||
def itransform(self, seq) -> None: | ||
def itransform(self, seq: MutableSequence[Sequence[float]]) -> None: | ||
"""Transform a sequence of points or vectors in-place. | ||
|
||
Parameters | ||
|
@@ -674,7 +645,7 @@ def __getnewargs__(self): | |
# Miscellaneous utilities | ||
|
||
|
||
def loadsw(s: str): | ||
def loadsw(s: str) -> Affine: | ||
"""Return Affine from the contents of a world file string. | ||
|
||
This method also translates the coefficients from center- to | ||
|
@@ -699,7 +670,7 @@ def loadsw(s: str): | |
return center * Affine.translation(-0.5, -0.5) | ||
|
||
|
||
def dumpsw(obj) -> str: | ||
def dumpsw(obj: Affine) -> str: | ||
"""Return string for a world file. | ||
|
||
This method also translates the coefficients from corner- to | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to type hinting: I removed a duplicated diagram.