[Git][debian-gis-team/python-affine][upstream] New upstream version 2.3.1

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Fri Mar 25 05:49:53 GMT 2022



Bas Couwenberg pushed to branch upstream at Debian GIS Project / python-affine


Commits:
9b68976e by Bas Couwenberg at 2022-03-25T06:40:58+01:00
New upstream version 2.3.1
- - - - -


7 changed files:

- .travis.yml
- CHANGES.txt
- README.rst
- affine/__init__.py
- affine/tests/test_transform.py
- − requirements.txt
- setup.py


Changes:

=====================================
.travis.yml
=====================================
@@ -5,12 +5,14 @@ python:
   - 2.7
   - 3.6
   - 3.7
+  - pypy3
 install:
-  - pip install -r requirements.txt
+  - pip install flake8 pydocstyle
   - pip install .[test]
 script:
-  - python -m pytest --cov affine --cov-report term-missing
+  - flake8
   - python -m pydocstyle affine
+  - python -m pytest --cov affine --cov-report term-missing
 after_success:
   - coveralls
 deploy:


=====================================
CHANGES.txt
=====================================
@@ -1,6 +1,14 @@
 CHANGES
 =======
 
+2.3.1 (2022-03-24)
+------------------
+
+Bug fixes:
+
+- Return NotImplemented for both ValueError and TypeError in __mul__ to support
+  fallback to __rmul__ in more cases (gh-71).
+
 2.3.0 (2019-09-04)
 ------------------
 


=====================================
README.rst
=====================================
@@ -18,7 +18,7 @@ Usage
 The 3x3 augmented affine transformation matrix for transformations in two
 dimensions is illustrated below.
 
-.. ::
+::
 
   | x' |   | a  b  c | | x |
   | y' | = | d  e  f | | y |
@@ -71,7 +71,7 @@ Usage with GIS data packages
 Georeferenced raster datasets use affine transformations to map from image
 coordinates to world coordinates. The ``affine.Affine.from_gdal()`` class
 method helps convert `GDAL GeoTransform
-<http://www.gdal.org/classGDALDataset.html#af9593cc241e7d140f5f3c4798a43a668>`__,
+<https://gdal.org/user/raster_data_model.html#affine-geotransform>`__,
 sequences of 6 numbers in which the first and fourth are the x and y offsets
 and the second and sixth are the x and y pixel sizes.
 


=====================================
affine/__init__.py
=====================================
@@ -41,7 +41,7 @@ import warnings
 
 __all__ = ['Affine']
 __author__ = "Sean Gillies"
-__version__ = "2.3.0"
+__version__ = "2.3.1"
 
 EPSILON = 1e-5
 
@@ -311,6 +311,16 @@ class Affine(
         """
         return (self.c, self.a, self.b, self.f, self.d, self.e)
 
+    def to_shapely(self):
+        """Return an affine transformation matrix compatible with shapely
+
+        Shapely's affinity module expects an affine transformation matrix
+        in (a,b,d,e,xoff,yoff) order.
+
+        :rtype: tuple
+        """
+        return (self.a, self.b, self.d, self.e, self.xoff, self.yoff)
+
     @property
     def xoff(self):
         """Alias for 'c'"""
@@ -374,7 +384,7 @@ class Affine(
         assuming it is in the form M = R S, where R is a rotation and S is a
         scaling.
 
-        Raises NotImplementedError for improper transformations.
+        Raises UndefinedRotationError for improper and degenerate transformations.
         """
         a, b, _, c, d, _, _, _, _ = self
         if self.is_proper or self.is_degenerate:
@@ -501,9 +511,9 @@ class Affine(
         else:
             try:
                 vx, vy = other
-            except Exception:
+                return (vx * sa + vy * sb + sc, vx * sd + vy * se + sf)
+            except (ValueError, TypeError):
                 return NotImplemented
-            return (vx * sa + vy * sb + sc, vx * sd + vy * se + sf)
 
     def __rmul__(self, other):
         """Right hand multiplication
@@ -518,7 +528,8 @@ class Affine(
         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)
+        warnings.warn("Right multiplication will be prohibited in version 3.0",
+                      DeprecationWarning, stacklevel=2)
         assert not isinstance(other, Affine)
         return self.__mul__(other)
 


=====================================
affine/tests/test_transform.py
=====================================
@@ -30,10 +30,9 @@
 
 from __future__ import division
 
-import os
 import math
 import unittest
-import textwrap
+from textwrap import dedent
 
 import pytest
 
@@ -101,14 +100,17 @@ class PyAffineTestCase(unittest.TestCase):
             t['foobar']
 
     def test_str(self):
-        assert \
-            str(Affine(1.111, 2.222, 3.333, -4.444, -5.555, 6.666)) \
-            == "| 1.11, 2.22, 3.33|\n|-4.44,-5.55, 6.67|\n| 0.00, 0.00, 1.00|"
+        t = Affine(1.111, 2.222, 3.333, -4.444, -5.555, 6.666)
+        assert str(t) == dedent("""\
+            | 1.11, 2.22, 3.33|
+            |-4.44,-5.55, 6.67|
+            | 0.00, 0.00, 1.00|""")
 
     def test_repr(self):
-        assert \
-            repr(Affine(1.111, 2.222, 3.456, 4.444, 5.5, 6.25)) == \
-            os.linesep.join(["Affine(1.111, 2.222, 3.456,", "       4.444, 5.5, 6.25)"])
+        t = Affine(1.111, 2.222, 3.456, 4.444, 5.5, 6.25)
+        assert repr(t) == dedent("""\
+            Affine(1.111, 2.222, 3.456,
+                   4.444, 5.5, 6.25)""")
 
     def test_identity_constructor(self):
         ident = Affine.identity()
@@ -128,8 +130,8 @@ class PyAffineTestCase(unittest.TestCase):
             (0, 1, 0,
              1, 0, 0,
              0, 0, 1)
-        assert (perm*perm).is_identity        
-        
+        assert (perm*perm).is_identity
+
     def test_translation_constructor(self):
         trans = Affine.translation(2, -5)
         assert isinstance(trans, Affine)
@@ -247,7 +249,8 @@ class PyAffineTestCase(unittest.TestCase):
              0, 0, 1)
 
     def test_rotation_constructor_with_pivot(self):
-        assert tuple(Affine.rotation(60)) == tuple(Affine.rotation(60, pivot=(0, 0)))
+        assert tuple(Affine.rotation(60)) == \
+            tuple(Affine.rotation(60, pivot=(0, 0)))
         rot = Affine.rotation(27, pivot=(2, -4))
         r = math.radians(27)
         s, c = math.sin(r), math.cos(r)
@@ -452,7 +455,7 @@ class PyAffineTestCase(unittest.TestCase):
         assert affine.dumpsw(a) == s
 
     def test_real_world(self):
-        s = textwrap.dedent('''\
+        s = dedent('''\
                  39.9317755024
                  30.0907511581
                  30.0907511576
@@ -481,10 +484,15 @@ def test_gdal():
     assert t.f == t.yoff == 237536.4
     assert t.d == 0.0
     assert t.e == -425.0
-    assert tuple(t) == (425.0, 0.0, -237481.5, 0.0, -425.0, 237536.4, 0, 0, 1.0)
+    assert tuple(t) == (425.0, 0.0, -237481.5, 0.0, -425.0, 237536.4, 0, 0, 1)
     assert t.to_gdal() == (-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0)
 
 
+def test_shapely():
+    t = Affine(425.0, 0.0, -237481.5, 0.0, -425.0, 237536.4)
+    assert t.to_shapely() == (425.0, 0.0, 0.0, -425, -237481.5, 237536.4)
+
+
 def test_imul_number():
     t = Affine(1, 2, 3, 4, 5, 6)
     try:
@@ -534,7 +542,7 @@ def test_roundtrip():
 def test_eccentricity():
     assert Affine.identity().eccentricity == 0.0
     assert Affine.scale(2).eccentricity == 0.0
-    #assert_equal(Affine.scale(0).eccentricity, ?)
+    # assert_equal(Affine.scale(0).eccentricity, ?)
     assert Affine.scale(2, 1).eccentricity == pytest.approx(math.sqrt(3) / 2)
     assert Affine.scale(2, 3).eccentricity == pytest.approx(math.sqrt(5) / 3)
     assert Affine.scale(1, 0).eccentricity == 1.0
@@ -551,7 +559,9 @@ def test_eccentricity_complex():
         (Affine.rotation(77) * Affine.scale(2, 3)).eccentricity == \
         pytest.approx(math.sqrt(5) / 3)
     assert \
-        (Affine.translation(32, -47) * Affine.rotation(77) * Affine.scale(2, 3)).eccentricity == \
+        (Affine.translation(32, -47) *
+         Affine.rotation(77) *
+         Affine.scale(2, 3)).eccentricity == \
         pytest.approx(math.sqrt(5) / 3)
 
 
@@ -569,5 +579,32 @@ def test_rotation_improper():
         Affine.scale(-1, 1).rotation_angle
 
 
+# See gh-71 for bug report motivating this test.
+def test_mul_fallback_unpack():
+    """Support fallback in case that other is a single object."""
+
+    class TextPoint:
+        """Not iterable, will trigger ValueError in Affine.__mul__."""
+        def __rmul__(self, other):
+            return other * (1, 2)
+
+    assert Affine.identity() * TextPoint() == (1, 2)
+
+
+# See gh-71 for bug report motivating this test.
+def test_mul_fallback_type_error():
+    """Support fallback in case that other is an unexpected type."""
+
+    class TextPoint:
+        """Iterable, but values trigger TypeError in Affine.__mul__."""
+        def __iter__(self):
+            return ("1", "2")
+
+        def __rmul__(self, other):
+            return other * (1, 2)
+
+    assert Affine.identity() * TextPoint() == (1, 2)
+
+
 if __name__ == '__main__':
     unittest.main()


=====================================
requirements.txt deleted
=====================================
@@ -1 +0,0 @@
-pydocstyle==2.1.1


=====================================
setup.py
=====================================
@@ -30,5 +30,6 @@ setup(
     packages=find_packages(exclude=["ez_setup", "examples", "tests"]),
     include_package_data=True,
     zip_safe=True,
-    extras_require={"test": ["pytest>=3.0", "pytest-cov", "pydocstyle", "coveralls"]},
+    extras_require={"test": ["pytest>=4.6", "pytest-cov", "pydocstyle",
+                             "flake8", "coveralls"]},
 )



View it on GitLab: https://salsa.debian.org/debian-gis-team/python-affine/-/commit/9b68976efb858818b14fbad5901d61e4e818b893

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-affine/-/commit/9b68976efb858818b14fbad5901d61e4e818b893
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20220325/c3fb4811/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list