We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
BUG: Missing _crs attribute when using sjoin on grouped gdf and latest version of pandas
- [x] I have checked that this issue has not already been reported.

- [x] I have confirmed this bug exists on the latest version of geopandas.

- [ ] (optional) I have confirmed this bug exists on the main branch of geopandas.

---

#### Code Sample, a copy-pastable example

```python
import geopandas as gpd
from geopandas import sjoin
from shapely.geometry import MultiPoint


pts = MultiPoint([[0, 0], [1, 1]])
polys = [_.buffer(0.1) for _ in pts.geoms]
gdf = gpd.GeoDataFrame(["a", "b"], geometry=polys)

df_close = gdf.groupby(0).apply(lambda x: sjoin(x, x, how="inner",
                                                predicate="overlaps"))
```

#### Problem description

Unsure if this is a pandas or a geopandas problem. With pandas 1.2.5, the MWE above works fine. With pandas 1.3.5, it fails; here's the traceback:

```python
Traceback (most recent call last):
  File "/Users/kylepenner/Desktop/bug.py", line 10, in <module>
    df_close = gdf.groupby(0).apply(lambda x: sjoin(x, x, how="inner",
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/groupby/groupby.py", line 1275, in apply
    result = self._python_apply_general(f, self._selected_obj)
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/groupby/groupby.py", line 1309, in _python_apply_general
    keys, values, mutated = self.grouper.apply(f, data, self.axis)
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/groupby/ops.py", line 852, in apply
    res = f(group)
  File "/Users/kylepenner/Desktop/bug.py", line 10, in <lambda>
    df_close = gdf.groupby(0).apply(lambda x: sjoin(x, x, how="inner",
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/tools/sjoin.py", line 122, in sjoin
    _basic_checks(left_df, right_df, how, lsuffix, rsuffix)
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/tools/sjoin.py", line 165, in _basic_checks
    if not _check_crs(left_df, right_df):
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/array.py", line 68, in _check_crs
    if not left.crs == right.crs:
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/generic.py", line 5487, in __getattr__
    return object.__getattribute__(self, name)
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/geodataframe.py", line 408, in crs
    return self._crs
  File "/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/generic.py", line 5487, in __getattr__
    return object.__getattribute__(self, name)
AttributeError: 'GeoDataFrame' object has no attribute '_crs'
```

#### Expected Output

A GeoDataFrame.

#### Output of ``geopandas.show_versions()``

<details>

SYSTEM INFO
-----------
python     : 3.10.1 | packaged by conda-forge | (main, Dec 22 2021, 01:39:14) [Clang 11.1.0 ]
executable : /Users/kylepenner/miniconda3/envs/test2/bin/python
machine    : macOS-11.6.2-x86_64-i386-64bit

GEOS, GDAL, PROJ INFO
---------------------
GEOS       : 3.10.1
GEOS lib   : /Users/kylepenner/miniconda3/envs/test2/lib/libgeos_c.dylib
GDAL       : 3.4.1
GDAL data dir: /Users/kylepenner/miniconda3/envs/test2/share/gdal
PROJ       : 8.2.1
PROJ data dir: /Users/kylepenner/miniconda3/envs/test2/share/proj

PYTHON DEPENDENCIES
-------------------
geopandas  : 0.10.2
pandas     : 1.3.5
fiona      : 1.8.20
numpy      : 1.22.0
shapely    : 1.8.0
rtree      : 0.9.7
pyproj     : 3.3.0
matplotlib : 3.5.1
mapclassify: 2.4.3
geopy      : None
psycopg2   : None
geoalchemy2: None
pyarrow    : None
pygeos     : None

</details>


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `geopandas/_compat.py`
Content:
```
1 import contextlib
2 from distutils.version import LooseVersion
3 import importlib
4 import os
5 import warnings
6 
7 import numpy as np
8 import pandas as pd
9 import pyproj
10 import shapely
11 import shapely.geos
12 
13 
14 # -----------------------------------------------------------------------------
15 # pandas compat
16 # -----------------------------------------------------------------------------
17 
18 PANDAS_GE_10 = str(pd.__version__) >= LooseVersion("1.0.0")
19 PANDAS_GE_11 = str(pd.__version__) >= LooseVersion("1.1.0")
20 PANDAS_GE_115 = str(pd.__version__) >= LooseVersion("1.1.5")
21 PANDAS_GE_12 = str(pd.__version__) >= LooseVersion("1.2.0")
22 PANDAS_GE_14 = str(pd.__version__) >= LooseVersion("1.4.0")
23 
24 
25 # -----------------------------------------------------------------------------
26 # Shapely / PyGEOS compat
27 # -----------------------------------------------------------------------------
28 
29 
30 SHAPELY_GE_17 = str(shapely.__version__) >= LooseVersion("1.7.0")
31 SHAPELY_GE_18 = str(shapely.__version__) >= LooseVersion("1.8")
32 SHAPELY_GE_20 = str(shapely.__version__) >= LooseVersion("2.0")
33 
34 GEOS_GE_390 = shapely.geos.geos_version >= (3, 9, 0)
35 
36 
37 HAS_PYGEOS = None
38 USE_PYGEOS = None
39 PYGEOS_SHAPELY_COMPAT = None
40 
41 PYGEOS_GE_09 = None
42 PYGEOS_GE_010 = None
43 
44 INSTALL_PYGEOS_ERROR = "To use PyGEOS within GeoPandas, you need to install PyGEOS: \
45 'conda install pygeos' or 'pip install pygeos'"
46 
47 try:
48     import pygeos  # noqa
49 
50     # only automatically use pygeos if version is high enough
51     if str(pygeos.__version__) >= LooseVersion("0.8"):
52         HAS_PYGEOS = True
53         PYGEOS_GE_09 = str(pygeos.__version__) >= LooseVersion("0.9")
54         PYGEOS_GE_010 = str(pygeos.__version__) >= LooseVersion("0.10")
55     else:
56         warnings.warn(
57             "The installed version of PyGEOS is too old ({0} installed, 0.8 required),"
58             " and thus GeoPandas will not use PyGEOS.".format(pygeos.__version__),
59             UserWarning,
60         )
61         HAS_PYGEOS = False
62 except ImportError:
63     HAS_PYGEOS = False
64 
65 
66 def set_use_pygeos(val=None):
67     """
68     Set the global configuration on whether to use PyGEOS or not.
69 
70     The default is use PyGEOS if it is installed. This can be overridden
71     with an environment variable USE_PYGEOS (this is only checked at
72     first import, cannot be changed during interactive session).
73 
74     Alternatively, pass a value here to force a True/False value.
75     """
76     global USE_PYGEOS
77     global PYGEOS_SHAPELY_COMPAT
78 
79     if val is not None:
80         USE_PYGEOS = bool(val)
81     else:
82         if USE_PYGEOS is None:
83 
84             USE_PYGEOS = HAS_PYGEOS
85 
86             env_use_pygeos = os.getenv("USE_PYGEOS", None)
87             if env_use_pygeos is not None:
88                 USE_PYGEOS = bool(int(env_use_pygeos))
89 
90     # validate the pygeos version
91     if USE_PYGEOS:
92         try:
93             import pygeos  # noqa
94 
95             # validate the pygeos version
96             if not str(pygeos.__version__) >= LooseVersion("0.8"):
97                 raise ImportError(
98                     "PyGEOS >= 0.8 is required, version {0} is installed".format(
99                         pygeos.__version__
100                     )
101                 )
102 
103             # Check whether Shapely and PyGEOS use the same GEOS version.
104             # Based on PyGEOS from_shapely implementation.
105 
106             from shapely.geos import geos_version_string as shapely_geos_version
107             from pygeos import geos_capi_version_string
108 
109             # shapely has something like: "3.6.2-CAPI-1.10.2 4d2925d6"
110             # pygeos has something like: "3.6.2-CAPI-1.10.2"
111             if not shapely_geos_version.startswith(geos_capi_version_string):
112                 warnings.warn(
113                     "The Shapely GEOS version ({}) is incompatible with the GEOS "
114                     "version PyGEOS was compiled with ({}). Conversions between both "
115                     "will be slow.".format(
116                         shapely_geos_version, geos_capi_version_string
117                     )
118                 )
119                 PYGEOS_SHAPELY_COMPAT = False
120             else:
121                 PYGEOS_SHAPELY_COMPAT = True
122 
123         except ImportError:
124             raise ImportError(INSTALL_PYGEOS_ERROR)
125 
126 
127 set_use_pygeos()
128 
129 
130 # compat related to deprecation warnings introduced in Shapely 1.8
131 # -> creating a numpy array from a list-like of Multi-part geometries,
132 # although doing the correct thing (not expanding in its parts), still raises
133 # the warning about iteration being deprecated
134 # This adds a context manager to explicitly ignore this warning
135 
136 
137 try:
138     from shapely.errors import ShapelyDeprecationWarning as shapely_warning
139 except ImportError:
140     shapely_warning = None
141 
142 
143 if shapely_warning is not None and not SHAPELY_GE_20:
144 
145     @contextlib.contextmanager
146     def ignore_shapely2_warnings():
147         with warnings.catch_warnings():
148             warnings.filterwarnings(
149                 "ignore", "Iteration|The array interface|__len__", shapely_warning
150             )
151             yield
152 
153 
154 elif (str(np.__version__) >= LooseVersion("1.21")) and not SHAPELY_GE_20:
155 
156     @contextlib.contextmanager
157     def ignore_shapely2_warnings():
158         with warnings.catch_warnings():
159             # warning from numpy for existing Shapely releases (this is fixed
160             # with Shapely 1.8)
161             warnings.filterwarnings(
162                 "ignore", "An exception was ignored while fetching", DeprecationWarning
163             )
164             yield
165 
166 
167 else:
168 
169     @contextlib.contextmanager
170     def ignore_shapely2_warnings():
171         yield
172 
173 
174 def import_optional_dependency(name: str, extra: str = ""):
175     """
176     Import an optional dependency.
177 
178     Adapted from pandas.compat._optional::import_optional_dependency
179 
180     Raises a formatted ImportError if the module is not present.
181 
182     Parameters
183     ----------
184     name : str
185         The module name.
186     extra : str
187         Additional text to include in the ImportError message.
188     Returns
189     -------
190     module
191     """
192     msg = """Missing optional dependency '{name}'. {extra}  "
193         "Use pip or conda to install {name}.""".format(
194         name=name, extra=extra
195     )
196 
197     if not isinstance(name, str):
198         raise ValueError(
199             "Invalid module name: '{name}'; must be a string".format(name=name)
200         )
201 
202     try:
203         module = importlib.import_module(name)
204 
205     except ImportError:
206         raise ImportError(msg) from None
207 
208     return module
209 
210 
211 # -----------------------------------------------------------------------------
212 # RTree compat
213 # -----------------------------------------------------------------------------
214 
215 HAS_RTREE = None
216 RTREE_GE_094 = False
217 try:
218     import rtree  # noqa
219 
220     HAS_RTREE = True
221 except ImportError:
222     HAS_RTREE = False
223 
224 # -----------------------------------------------------------------------------
225 # pyproj compat
226 # -----------------------------------------------------------------------------
227 
228 PYPROJ_LT_3 = LooseVersion(pyproj.__version__) < LooseVersion("3")
229 PYPROJ_GE_31 = LooseVersion(pyproj.__version__) >= LooseVersion("3.1")
230
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/geopandas/_compat.py b/geopandas/_compat.py
--- a/geopandas/_compat.py
+++ b/geopandas/_compat.py
@@ -19,6 +19,7 @@
 PANDAS_GE_11 = str(pd.__version__) >= LooseVersion("1.1.0")
 PANDAS_GE_115 = str(pd.__version__) >= LooseVersion("1.1.5")
 PANDAS_GE_12 = str(pd.__version__) >= LooseVersion("1.2.0")
+PANDAS_GE_13 = str(pd.__version__) >= LooseVersion("1.3.0")
 PANDAS_GE_14 = str(pd.__version__) >= LooseVersion("1.4.0")

{"golden_diff": "diff --git a/geopandas/_compat.py b/geopandas/_compat.py\n--- a/geopandas/_compat.py\n+++ b/geopandas/_compat.py\n@@ -19,6 +19,7 @@\n PANDAS_GE_11 = str(pd.__version__) >= LooseVersion(\"1.1.0\")\n PANDAS_GE_115 = str(pd.__version__) >= LooseVersion(\"1.1.5\")\n PANDAS_GE_12 = str(pd.__version__) >= LooseVersion(\"1.2.0\")\n+PANDAS_GE_13 = str(pd.__version__) >= LooseVersion(\"1.3.0\")\n PANDAS_GE_14 = str(pd.__version__) >= LooseVersion(\"1.4.0\")\n", "issue": "BUG: Missing _crs attribute when using sjoin on grouped gdf and latest version of pandas\n- [x] I have checked that this issue has not already been reported.\r\n\r\n- [x] I have confirmed this bug exists on the latest version of geopandas.\r\n\r\n- [ ] (optional) I have confirmed this bug exists on the main branch of geopandas.\r\n\r\n---\r\n\r\n#### Code Sample, a copy-pastable example\r\n\r\n```python\r\nimport geopandas as gpd\r\nfrom geopandas import sjoin\r\nfrom shapely.geometry import MultiPoint\r\n\r\n\r\npts = MultiPoint([[0, 0], [1, 1]])\r\npolys = [_.buffer(0.1) for _ in pts.geoms]\r\ngdf = gpd.GeoDataFrame([\"a\", \"b\"], geometry=polys)\r\n\r\ndf_close = gdf.groupby(0).apply(lambda x: sjoin(x, x, how=\"inner\",\r\n                                                predicate=\"overlaps\"))\r\n```\r\n\r\n#### Problem description\r\n\r\nUnsure if this is a pandas or a geopandas problem. With pandas 1.2.5, the MWE above works fine. With pandas 1.3.5, it fails; here's the traceback:\r\n\r\n```python\r\nTraceback (most recent call last):\r\n  File \"/Users/kylepenner/Desktop/bug.py\", line 10, in <module>\r\n    df_close = gdf.groupby(0).apply(lambda x: sjoin(x, x, how=\"inner\",\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/groupby/groupby.py\", line 1275, in apply\r\n    result = self._python_apply_general(f, self._selected_obj)\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/groupby/groupby.py\", line 1309, in _python_apply_general\r\n    keys, values, mutated = self.grouper.apply(f, data, self.axis)\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/groupby/ops.py\", line 852, in apply\r\n    res = f(group)\r\n  File \"/Users/kylepenner/Desktop/bug.py\", line 10, in <lambda>\r\n    df_close = gdf.groupby(0).apply(lambda x: sjoin(x, x, how=\"inner\",\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/tools/sjoin.py\", line 122, in sjoin\r\n    _basic_checks(left_df, right_df, how, lsuffix, rsuffix)\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/tools/sjoin.py\", line 165, in _basic_checks\r\n    if not _check_crs(left_df, right_df):\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/array.py\", line 68, in _check_crs\r\n    if not left.crs == right.crs:\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/generic.py\", line 5487, in __getattr__\r\n    return object.__getattribute__(self, name)\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/geopandas/geodataframe.py\", line 408, in crs\r\n    return self._crs\r\n  File \"/Users/kylepenner/miniconda3/envs/test2/lib/python3.10/site-packages/pandas/core/generic.py\", line 5487, in __getattr__\r\n    return object.__getattribute__(self, name)\r\nAttributeError: 'GeoDataFrame' object has no attribute '_crs'\r\n```\r\n\r\n#### Expected Output\r\n\r\nA GeoDataFrame.\r\n\r\n#### Output of ``geopandas.show_versions()``\r\n\r\n<details>\r\n\r\nSYSTEM INFO\r\n-----------\r\npython     : 3.10.1 | packaged by conda-forge | (main, Dec 22 2021, 01:39:14) [Clang 11.1.0 ]\r\nexecutable : /Users/kylepenner/miniconda3/envs/test2/bin/python\r\nmachine    : macOS-11.6.2-x86_64-i386-64bit\r\n\r\nGEOS, GDAL, PROJ INFO\r\n---------------------\r\nGEOS       : 3.10.1\r\nGEOS lib   : /Users/kylepenner/miniconda3/envs/test2/lib/libgeos_c.dylib\r\nGDAL       : 3.4.1\r\nGDAL data dir: /Users/kylepenner/miniconda3/envs/test2/share/gdal\r\nPROJ       : 8.2.1\r\nPROJ data dir: /Users/kylepenner/miniconda3/envs/test2/share/proj\r\n\r\nPYTHON DEPENDENCIES\r\n-------------------\r\ngeopandas  : 0.10.2\r\npandas     : 1.3.5\r\nfiona      : 1.8.20\r\nnumpy      : 1.22.0\r\nshapely    : 1.8.0\r\nrtree      : 0.9.7\r\npyproj     : 3.3.0\r\nmatplotlib : 3.5.1\r\nmapclassify: 2.4.3\r\ngeopy      : None\r\npsycopg2   : None\r\ngeoalchemy2: None\r\npyarrow    : None\r\npygeos     : None\r\n\r\n</details>\r\n\n", "before_files": [{"content": "import contextlib\nfrom distutils.version import LooseVersion\nimport importlib\nimport os\nimport warnings\n\nimport numpy as np\nimport pandas as pd\nimport pyproj\nimport shapely\nimport shapely.geos\n\n\n# -----------------------------------------------------------------------------\n# pandas compat\n# -----------------------------------------------------------------------------\n\nPANDAS_GE_10 = str(pd.__version__) >= LooseVersion(\"1.0.0\")\nPANDAS_GE_11 = str(pd.__version__) >= LooseVersion(\"1.1.0\")\nPANDAS_GE_115 = str(pd.__version__) >= LooseVersion(\"1.1.5\")\nPANDAS_GE_12 = str(pd.__version__) >= LooseVersion(\"1.2.0\")\nPANDAS_GE_14 = str(pd.__version__) >= LooseVersion(\"1.4.0\")\n\n\n# -----------------------------------------------------------------------------\n# Shapely / PyGEOS compat\n# -----------------------------------------------------------------------------\n\n\nSHAPELY_GE_17 = str(shapely.__version__) >= LooseVersion(\"1.7.0\")\nSHAPELY_GE_18 = str(shapely.__version__) >= LooseVersion(\"1.8\")\nSHAPELY_GE_20 = str(shapely.__version__) >= LooseVersion(\"2.0\")\n\nGEOS_GE_390 = shapely.geos.geos_version >= (3, 9, 0)\n\n\nHAS_PYGEOS = None\nUSE_PYGEOS = None\nPYGEOS_SHAPELY_COMPAT = None\n\nPYGEOS_GE_09 = None\nPYGEOS_GE_010 = None\n\nINSTALL_PYGEOS_ERROR = \"To use PyGEOS within GeoPandas, you need to install PyGEOS: \\\n'conda install pygeos' or 'pip install pygeos'\"\n\ntry:\n    import pygeos  # noqa\n\n    # only automatically use pygeos if version is high enough\n    if str(pygeos.__version__) >= LooseVersion(\"0.8\"):\n        HAS_PYGEOS = True\n        PYGEOS_GE_09 = str(pygeos.__version__) >= LooseVersion(\"0.9\")\n        PYGEOS_GE_010 = str(pygeos.__version__) >= LooseVersion(\"0.10\")\n    else:\n        warnings.warn(\n            \"The installed version of PyGEOS is too old ({0} installed, 0.8 required),\"\n            \" and thus GeoPandas will not use PyGEOS.\".format(pygeos.__version__),\n            UserWarning,\n        )\n        HAS_PYGEOS = False\nexcept ImportError:\n    HAS_PYGEOS = False\n\n\ndef set_use_pygeos(val=None):\n    \"\"\"\n    Set the global configuration on whether to use PyGEOS or not.\n\n    The default is use PyGEOS if it is installed. This can be overridden\n    with an environment variable USE_PYGEOS (this is only checked at\n    first import, cannot be changed during interactive session).\n\n    Alternatively, pass a value here to force a True/False value.\n    \"\"\"\n    global USE_PYGEOS\n    global PYGEOS_SHAPELY_COMPAT\n\n    if val is not None:\n        USE_PYGEOS = bool(val)\n    else:\n        if USE_PYGEOS is None:\n\n            USE_PYGEOS = HAS_PYGEOS\n\n            env_use_pygeos = os.getenv(\"USE_PYGEOS\", None)\n            if env_use_pygeos is not None:\n                USE_PYGEOS = bool(int(env_use_pygeos))\n\n    # validate the pygeos version\n    if USE_PYGEOS:\n        try:\n            import pygeos  # noqa\n\n            # validate the pygeos version\n            if not str(pygeos.__version__) >= LooseVersion(\"0.8\"):\n                raise ImportError(\n                    \"PyGEOS >= 0.8 is required, version {0} is installed\".format(\n                        pygeos.__version__\n                    )\n                )\n\n            # Check whether Shapely and PyGEOS use the same GEOS version.\n            # Based on PyGEOS from_shapely implementation.\n\n            from shapely.geos import geos_version_string as shapely_geos_version\n            from pygeos import geos_capi_version_string\n\n            # shapely has something like: \"3.6.2-CAPI-1.10.2 4d2925d6\"\n            # pygeos has something like: \"3.6.2-CAPI-1.10.2\"\n            if not shapely_geos_version.startswith(geos_capi_version_string):\n                warnings.warn(\n                    \"The Shapely GEOS version ({}) is incompatible with the GEOS \"\n                    \"version PyGEOS was compiled with ({}). Conversions between both \"\n                    \"will be slow.\".format(\n                        shapely_geos_version, geos_capi_version_string\n                    )\n                )\n                PYGEOS_SHAPELY_COMPAT = False\n            else:\n                PYGEOS_SHAPELY_COMPAT = True\n\n        except ImportError:\n            raise ImportError(INSTALL_PYGEOS_ERROR)\n\n\nset_use_pygeos()\n\n\n# compat related to deprecation warnings introduced in Shapely 1.8\n# -> creating a numpy array from a list-like of Multi-part geometries,\n# although doing the correct thing (not expanding in its parts), still raises\n# the warning about iteration being deprecated\n# This adds a context manager to explicitly ignore this warning\n\n\ntry:\n    from shapely.errors import ShapelyDeprecationWarning as shapely_warning\nexcept ImportError:\n    shapely_warning = None\n\n\nif shapely_warning is not None and not SHAPELY_GE_20:\n\n    @contextlib.contextmanager\n    def ignore_shapely2_warnings():\n        with warnings.catch_warnings():\n            warnings.filterwarnings(\n                \"ignore\", \"Iteration|The array interface|__len__\", shapely_warning\n            )\n            yield\n\n\nelif (str(np.__version__) >= LooseVersion(\"1.21\")) and not SHAPELY_GE_20:\n\n    @contextlib.contextmanager\n    def ignore_shapely2_warnings():\n        with warnings.catch_warnings():\n            # warning from numpy for existing Shapely releases (this is fixed\n            # with Shapely 1.8)\n            warnings.filterwarnings(\n                \"ignore\", \"An exception was ignored while fetching\", DeprecationWarning\n            )\n            yield\n\n\nelse:\n\n    @contextlib.contextmanager\n    def ignore_shapely2_warnings():\n        yield\n\n\ndef import_optional_dependency(name: str, extra: str = \"\"):\n    \"\"\"\n    Import an optional dependency.\n\n    Adapted from pandas.compat._optional::import_optional_dependency\n\n    Raises a formatted ImportError if the module is not present.\n\n    Parameters\n    ----------\n    name : str\n        The module name.\n    extra : str\n        Additional text to include in the ImportError message.\n    Returns\n    -------\n    module\n    \"\"\"\n    msg = \"\"\"Missing optional dependency '{name}'. {extra}  \"\n        \"Use pip or conda to install {name}.\"\"\".format(\n        name=name, extra=extra\n    )\n\n    if not isinstance(name, str):\n        raise ValueError(\n            \"Invalid module name: '{name}'; must be a string\".format(name=name)\n        )\n\n    try:\n        module = importlib.import_module(name)\n\n    except ImportError:\n        raise ImportError(msg) from None\n\n    return module\n\n\n# -----------------------------------------------------------------------------\n# RTree compat\n# -----------------------------------------------------------------------------\n\nHAS_RTREE = None\nRTREE_GE_094 = False\ntry:\n    import rtree  # noqa\n\n    HAS_RTREE = True\nexcept ImportError:\n    HAS_RTREE = False\n\n# -----------------------------------------------------------------------------\n# pyproj compat\n# -----------------------------------------------------------------------------\n\nPYPROJ_LT_3 = LooseVersion(pyproj.__version__) < LooseVersion(\"3\")\nPYPROJ_GE_31 = LooseVersion(pyproj.__version__) >= LooseVersion(\"3.1\")\n", "path": "geopandas/_compat.py"}], "after_files": [{"content": "import contextlib\nfrom distutils.version import LooseVersion\nimport importlib\nimport os\nimport warnings\n\nimport numpy as np\nimport pandas as pd\nimport pyproj\nimport shapely\nimport shapely.geos\n\n\n# -----------------------------------------------------------------------------\n# pandas compat\n# -----------------------------------------------------------------------------\n\nPANDAS_GE_10 = str(pd.__version__) >= LooseVersion(\"1.0.0\")\nPANDAS_GE_11 = str(pd.__version__) >= LooseVersion(\"1.1.0\")\nPANDAS_GE_115 = str(pd.__version__) >= LooseVersion(\"1.1.5\")\nPANDAS_GE_12 = str(pd.__version__) >= LooseVersion(\"1.2.0\")\nPANDAS_GE_13 = str(pd.__version__) >= LooseVersion(\"1.3.0\")\nPANDAS_GE_14 = str(pd.__version__) >= LooseVersion(\"1.4.0\")\n\n\n# -----------------------------------------------------------------------------\n# Shapely / PyGEOS compat\n# -----------------------------------------------------------------------------\n\n\nSHAPELY_GE_17 = str(shapely.__version__) >= LooseVersion(\"1.7.0\")\nSHAPELY_GE_18 = str(shapely.__version__) >= LooseVersion(\"1.8\")\nSHAPELY_GE_20 = str(shapely.__version__) >= LooseVersion(\"2.0\")\n\nGEOS_GE_390 = shapely.geos.geos_version >= (3, 9, 0)\n\n\nHAS_PYGEOS = None\nUSE_PYGEOS = None\nPYGEOS_SHAPELY_COMPAT = None\n\nPYGEOS_GE_09 = None\nPYGEOS_GE_010 = None\n\nINSTALL_PYGEOS_ERROR = \"To use PyGEOS within GeoPandas, you need to install PyGEOS: \\\n'conda install pygeos' or 'pip install pygeos'\"\n\ntry:\n    import pygeos  # noqa\n\n    # only automatically use pygeos if version is high enough\n    if str(pygeos.__version__) >= LooseVersion(\"0.8\"):\n        HAS_PYGEOS = True\n        PYGEOS_GE_09 = str(pygeos.__version__) >= LooseVersion(\"0.9\")\n        PYGEOS_GE_010 = str(pygeos.__version__) >= LooseVersion(\"0.10\")\n    else:\n        warnings.warn(\n            \"The installed version of PyGEOS is too old ({0} installed, 0.8 required),\"\n            \" and thus GeoPandas will not use PyGEOS.\".format(pygeos.__version__),\n            UserWarning,\n        )\n        HAS_PYGEOS = False\nexcept ImportError:\n    HAS_PYGEOS = False\n\n\ndef set_use_pygeos(val=None):\n    \"\"\"\n    Set the global configuration on whether to use PyGEOS or not.\n\n    The default is use PyGEOS if it is installed. This can be overridden\n    with an environment variable USE_PYGEOS (this is only checked at\n    first import, cannot be changed during interactive session).\n\n    Alternatively, pass a value here to force a True/False value.\n    \"\"\"\n    global USE_PYGEOS\n    global PYGEOS_SHAPELY_COMPAT\n\n    if val is not None:\n        USE_PYGEOS = bool(val)\n    else:\n        if USE_PYGEOS is None:\n\n            USE_PYGEOS = HAS_PYGEOS\n\n            env_use_pygeos = os.getenv(\"USE_PYGEOS\", None)\n            if env_use_pygeos is not None:\n                USE_PYGEOS = bool(int(env_use_pygeos))\n\n    # validate the pygeos version\n    if USE_PYGEOS:\n        try:\n            import pygeos  # noqa\n\n            # validate the pygeos version\n            if not str(pygeos.__version__) >= LooseVersion(\"0.8\"):\n                raise ImportError(\n                    \"PyGEOS >= 0.8 is required, version {0} is installed\".format(\n                        pygeos.__version__\n                    )\n                )\n\n            # Check whether Shapely and PyGEOS use the same GEOS version.\n            # Based on PyGEOS from_shapely implementation.\n\n            from shapely.geos import geos_version_string as shapely_geos_version\n            from pygeos import geos_capi_version_string\n\n            # shapely has something like: \"3.6.2-CAPI-1.10.2 4d2925d6\"\n            # pygeos has something like: \"3.6.2-CAPI-1.10.2\"\n            if not shapely_geos_version.startswith(geos_capi_version_string):\n                warnings.warn(\n                    \"The Shapely GEOS version ({}) is incompatible with the GEOS \"\n                    \"version PyGEOS was compiled with ({}). Conversions between both \"\n                    \"will be slow.\".format(\n                        shapely_geos_version, geos_capi_version_string\n                    )\n                )\n                PYGEOS_SHAPELY_COMPAT = False\n            else:\n                PYGEOS_SHAPELY_COMPAT = True\n\n        except ImportError:\n            raise ImportError(INSTALL_PYGEOS_ERROR)\n\n\nset_use_pygeos()\n\n\n# compat related to deprecation warnings introduced in Shapely 1.8\n# -> creating a numpy array from a list-like of Multi-part geometries,\n# although doing the correct thing (not expanding in its parts), still raises\n# the warning about iteration being deprecated\n# This adds a context manager to explicitly ignore this warning\n\n\ntry:\n    from shapely.errors import ShapelyDeprecationWarning as shapely_warning\nexcept ImportError:\n    shapely_warning = None\n\n\nif shapely_warning is not None and not SHAPELY_GE_20:\n\n    @contextlib.contextmanager\n    def ignore_shapely2_warnings():\n        with warnings.catch_warnings():\n            warnings.filterwarnings(\n                \"ignore\", \"Iteration|The array interface|__len__\", shapely_warning\n            )\n            yield\n\n\nelif (str(np.__version__) >= LooseVersion(\"1.21\")) and not SHAPELY_GE_20:\n\n    @contextlib.contextmanager\n    def ignore_shapely2_warnings():\n        with warnings.catch_warnings():\n            # warning from numpy for existing Shapely releases (this is fixed\n            # with Shapely 1.8)\n            warnings.filterwarnings(\n                \"ignore\", \"An exception was ignored while fetching\", DeprecationWarning\n            )\n            yield\n\n\nelse:\n\n    @contextlib.contextmanager\n    def ignore_shapely2_warnings():\n        yield\n\n\ndef import_optional_dependency(name: str, extra: str = \"\"):\n    \"\"\"\n    Import an optional dependency.\n\n    Adapted from pandas.compat._optional::import_optional_dependency\n\n    Raises a formatted ImportError if the module is not present.\n\n    Parameters\n    ----------\n    name : str\n        The module name.\n    extra : str\n        Additional text to include in the ImportError message.\n    Returns\n    -------\n    module\n    \"\"\"\n    msg = \"\"\"Missing optional dependency '{name}'. {extra}  \"\n        \"Use pip or conda to install {name}.\"\"\".format(\n        name=name, extra=extra\n    )\n\n    if not isinstance(name, str):\n        raise ValueError(\n            \"Invalid module name: '{name}'; must be a string\".format(name=name)\n        )\n\n    try:\n        module = importlib.import_module(name)\n\n    except ImportError:\n        raise ImportError(msg) from None\n\n    return module\n\n\n# -----------------------------------------------------------------------------\n# RTree compat\n# -----------------------------------------------------------------------------\n\nHAS_RTREE = None\nRTREE_GE_094 = False\ntry:\n    import rtree  # noqa\n\n    HAS_RTREE = True\nexcept ImportError:\n    HAS_RTREE = False\n\n# -----------------------------------------------------------------------------\n# pyproj compat\n# -----------------------------------------------------------------------------\n\nPYPROJ_LT_3 = LooseVersion(pyproj.__version__) < LooseVersion(\"3\")\nPYPROJ_GE_31 = LooseVersion(pyproj.__version__) >= LooseVersion(\"3.1\")\n", "path": "geopandas/_compat.py"}]}