Repository: geopandas/geopandas

Issue:
TST: TestSeries.test_proj4strings fails with PROJ 8.0.1
We have a new failure likely caused by PROJ 8.0.1. It worked with PROJ 8.0.0.

@snowman2 where should this be reported?

https://github.com/geopandas/geopandas/runs/2723837365?check_suite_focus=true#step:6:2654

```
_________________________ TestSeries.test_proj4strings _________________________
[gw0] linux -- Python 3.8.10 /usr/share/miniconda/envs/test/bin/python

self = <geopandas.tests.test_geoseries.TestSeries object at 0x7f22fc561d90>

    def test_proj4strings(self):
        # As string
>       reprojected = self.g3.to_crs("+proj=utm +zone=30N")

geopandas/tests/test_geoseries.py:265: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
geopandas/geoseries.py:1036: in to_crs
    self.values.to_crs(crs=crs, epsg=epsg), index=self.index, name=self.name
geopandas/array.py:768: in to_crs
    crs = CRS.from_user_input(crs)
/usr/share/miniconda/envs/test/lib/python3.8/site-packages/pyproj/crs/crs.py:466: in from_user_input
    return CRS(value, **kwargs)
/usr/share/miniconda/envs/test/lib/python3.8/site-packages/pyproj/crs/crs.py:313: in __init__
    self._local.crs = _CRS(self.srs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???

E   pyproj.exceptions.CRSError: Invalid projection: +proj=utm +zone=30N +type=crs: (Internal Proj Error: proj_create: Error 1027 (Invalid value for an argument): utm: Invalid value for zone)

pyproj/_crs.pyx:2326: CRSError
```


Discussion:
Can you reproduce the issue with the `proj`\ `projinfo` commands?
I see "UTM: error out when value of +zone= is not an integer (#2672)" in the news file of the latest release: https://github.com/OSGeo/PROJ/blob/fdfeae1908e8bf9e199aed3654ff418aaaa4fe26/NEWS#L20. So this was probably on purpose.

-> https://github.com/OSGeo/PROJ/issues/2671
>> But so this only happened to work "by accident" before? (because the north zone is the default, eg using +zone=30S would still give the north zone)

>yes.

(https://github.com/OSGeo/PROJ/issues/2671#issuecomment-852985459)

This is interesting. We should probably change the test on our side then. 

Resolving patch:
diff --git a/geopandas/geoseries.py b/geopandas/geoseries.py
--- a/geopandas/geoseries.py
+++ b/geopandas/geoseries.py
@@ -132,9 +132,9 @@ class GeoSeries(GeoPandasBase, Series):
     - Lat[north]: Geodetic latitude (degree)
     - Lon[east]: Geodetic longitude (degree)
     Area of Use:
-    - name: World
+    - name: World.
     - bounds: (-180.0, -90.0, 180.0, 90.0)
-    Datum: World Geodetic System 1984
+    Datum: World Geodetic System 1984 ensemble
     - Ellipsoid: WGS 84
     - Prime Meridian: Greenwich
 
@@ -578,7 +578,7 @@ def apply(self, func, convert_dtype=True, args=(), **kwargs):
         return result
 
     def __finalize__(self, other, method=None, **kwargs):
-        """ propagate metadata from other to self """
+        """propagate metadata from other to self"""
         # NOTE: backported from pandas master (upcoming v0.13)
         for name in self._metadata:
             object.__setattr__(self, name, getattr(other, name, None))


Test patch:
diff --git a/geopandas/tests/test_geoseries.py b/geopandas/tests/test_geoseries.py
--- a/geopandas/tests/test_geoseries.py
+++ b/geopandas/tests/test_geoseries.py
@@ -262,25 +262,25 @@ def test_geoseries_geointerface(self):
 
     def test_proj4strings(self):
         # As string
-        reprojected = self.g3.to_crs("+proj=utm +zone=30N")
+        reprojected = self.g3.to_crs("+proj=utm +zone=30")
         reprojected_back = reprojected.to_crs(epsg=4326)
         assert np.all(self.g3.geom_almost_equals(reprojected_back))
 
         # As dict
-        reprojected = self.g3.to_crs({"proj": "utm", "zone": "30N"})
+        reprojected = self.g3.to_crs({"proj": "utm", "zone": "30"})
         reprojected_back = reprojected.to_crs(epsg=4326)
         assert np.all(self.g3.geom_almost_equals(reprojected_back))
 
         # Set to equivalent string, convert, compare to original
         copy = self.g3.copy()
         copy.crs = "epsg:4326"
-        reprojected = copy.to_crs({"proj": "utm", "zone": "30N"})
+        reprojected = copy.to_crs({"proj": "utm", "zone": "30"})
         reprojected_back = reprojected.to_crs(epsg=4326)
         assert np.all(self.g3.geom_almost_equals(reprojected_back))
 
         # Conversions by different format
-        reprojected_string = self.g3.to_crs("+proj=utm +zone=30N")
-        reprojected_dict = self.g3.to_crs({"proj": "utm", "zone": "30N"})
+        reprojected_string = self.g3.to_crs("+proj=utm +zone=30")
+        reprojected_dict = self.g3.to_crs({"proj": "utm", "zone": "30"})
         assert np.all(reprojected_string.geom_almost_equals(reprojected_dict))
 
     def test_from_wkb(self):