Repository: regionmask/regionmask

Issue:
fix overlap default and docstring in 
In 3439 I forgot to change the default and the docstring for the `from_*` methods/ functions.

https://github.com/regionmask/regionmask/blob/a9bbdf3318a3e39937f59da525ecef1a5e9046e3/regionmask/core/_geopandas.py#L71

https://github.com/regionmask/regionmask/blob/a9bbdf3318a3e39937f59da525ecef1a5e9046e3/regionmask/core/regions.py#L477

https://github.com/regionmask/regionmask/blob/a9bbdf3318a3e39937f59da525ecef1a5e9046e3/regionmask/core/regions.py#L523

Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/regionmask/regionmask/pull/470?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) Report
> Merging [#470](https://app.codecov.io/gh/regionmask/regionmask/pull/470?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) (9ff4baf) into [main](https://app.codecov.io/gh/regionmask/regionmask/commit/a9bbdf3318a3e39937f59da525ecef1a5e9046e3?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) (a9bbdf3) will **decrease** coverage by `0.36%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##             main     #470      +/-   ##
==========================================
- Coverage   97.88%   97.52%   -0.36%     
==========================================
  Files          17       17              
  Lines        1416     1416              
==========================================
- Hits         1386     1381       -5     
- Misses         30       35       +5     
```

| [Flag](https://app.codecov.io/gh/regionmask/regionmask/pull/470/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | Coverage Δ | |
|---|---|---|
| [bare-minimum](https://app.codecov.io/gh/regionmask/regionmask/pull/470/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `?` | |
| [min-all-deps](https://app.codecov.io/gh/regionmask/regionmask/pull/470/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `95.55% <100.00%> (ø)` | |
| [shapely_lt_2](https://app.codecov.io/gh/regionmask/regionmask/pull/470/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `94.27% <100.00%> (ø)` | |
| [unittests](https://app.codecov.io/gh/regionmask/regionmask/pull/470/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | `97.52% <100.00%> (-0.36%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Files](https://app.codecov.io/gh/regionmask/regionmask/pull/470?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask) | Coverage Δ | |
|---|---|---|
| [regionmask/core/\_geopandas.py](https://app.codecov.io/gh/regionmask/regionmask/pull/470?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL19nZW9wYW5kYXMucHk=) | `97.53% <ø> (ø)` | |
| [regionmask/core/regions.py](https://app.codecov.io/gh/regionmask/regionmask/pull/470?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask#diff-cmVnaW9ubWFzay9jb3JlL3JlZ2lvbnMucHk=) | `97.53% <100.00%> (ø)` | |

... and [2 files with indirect coverage changes](https://app.codecov.io/gh/regionmask/regionmask/pull/470/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=regionmask)



Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index fbec418..84b6128 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -17,6 +17,8 @@ Breaking Changes
 ~~~~~~~~~~~~~~~~
 
 - Removed support for Python 3.8 (:pull:`465`).
+- Removed the ``regionmask.defined_regions.natural_earth`` regions which were deprecated
+  in v0.9.0 (:pull:`479`)
 - Removed the deprecated ``subsample`` keyword from the plotting methods (:pull:`468`).
 - Removed the deprecated ``_ar6_pre_revisions`` regions (:pull:`#466`).
 
@@ -32,11 +34,14 @@ New regions
 Bug Fixes
 ~~~~~~~~~
 
+- Fixed the default value of ``overlap`` of :py:func:`from_geopandas` to ``None`` (:issue:`453`, :pull:`470`).
+
 Docs
 ~~~~
 
 - Updated the "Using regionmask with intake" example (:pull:`477`).
 - Fixed the url to the MEOW dataset in the intake example (:pull:`474` and :pull:`477`).
+- Fixed the docstring for ``overlap`` of :py:func:`from_geopandas` and :py:class:`Regions` (:issue:`453`, :pull:`470`).
 
 Internal Changes
 ~~~~~~~~~~~~~~~~
diff --git a/regionmask/core/_geopandas.py b/regionmask/core/_geopandas.py
index 0d5b96a..05a7440 100644
--- a/regionmask/core/_geopandas.py
+++ b/regionmask/core/_geopandas.py
@@ -68,7 +68,7 @@ def from_geopandas(
     abbrevs=None,
     name="unnamed",
     source=None,
-    overlap=False,
+    overlap=None,
 ):
     """
     Create ``regionmask.Regions`` from a ``geopandas.GeoDataFrame``.
@@ -98,16 +98,18 @@ def from_geopandas(
     source : str, optional
         source of the shapefile
 
-    overlap : bool, default: False
-        Indicates if (some of) the regions overlap. If True ``mask_3D`` will ensure
-        overlapping regions are correctly assigned to grid points while ``mask`` will
-        error (because overlapping regions cannot be represented by a 2D mask).
-
-        If False (default) assumes non-overlapping regions. Grid points will
-        silently be assigned to the region with the higher number (this may change
-        in a future version).
-
-        There is (currently) no automatic detection of overlapping regions.
+    overlap : bool | None, default: None
+        Indicates if (some of) the regions overlap and determines the behaviour of the
+        ``mask`` methods.
+
+        - If True ``mask_3D`` ensures overlapping regions are correctly assigned
+          to grid points, while ``mask`` raises an Error (because overlapping
+          regions cannot be represented by a 2 dimensional mask).
+        - If False assumes non-overlapping regions. Grid points are silently assigned to the
+          region with the higher number.
+        - If None (default) checks if any gridpoint belongs to more than one region.
+          If this is the case ``mask_3D`` correctly assigns them and ``mask``
+          raises an Error.
 
     Returns
     -------
diff --git a/regionmask/core/regions.py b/regionmask/core/regions.py
index ec196b3..976fc06 100644
--- a/regionmask/core/regions.py
+++ b/regionmask/core/regions.py
@@ -43,10 +43,11 @@ class Regions:
     source : string, optional
         Source of the region definitions. Default: "".
     overlap : bool | None, default: None
-        Indicates if (some of) the regions overlap.
+        Indicates if (some of) the regions overlap  and determines the behaviour of the
+        ``mask`` methods.
 
         - If True ``Regions.mask_3D`` ensures overlapping regions are correctly assigned
-          to grid points, while ``Regionsmask`` raises an Error  (because overlapping
+          to grid points, while ``Regions.mask`` raises an Error  (because overlapping
           regions cannot be represented by a 2D mask).
         - If False assumes non-overlapping regions. Grid points are silently assigned to
           the region with the higher number.
@@ -482,17 +483,18 @@ class Regions:
         source : str, optional
             Source of the shapefile.  If None uses ``df.attrs.get("source")``.
 
-        overlap : bool, default: None
-            Indicates if (some of) the regions overlap. If None uses
-            ``df.attrs.get("overlap")``. If True ``mask_3D`` will ensure
-            overlapping regions are correctly assigned to grid points while ``mask``
-            will error (because overlapping regions cannot be represented by a 2D mask).
+        overlap : bool | None, default: None
+            Indicates if (some of) the regions overlap and determines the behaviour of the
+            ``mask`` methods.
 
-            If False assumes non-overlapping regions. Grid points will silently be
-            assigned to the region with the higher number (this may change in a future
-            version).
-
-            There is (currently) no automatic detection of overlapping regions.
+            - If True ``mask_3D`` ensures overlapping regions are correctly assigned
+              to grid points, while ``mask`` raises an Error (because overlapping
+              regions cannot be represented by a 2 dimensional mask).
+            - If False assumes non-overlapping regions. Grid points are silently assigned to the
+              region with the higher number.
+            - If None (default) checks if any gridpoint belongs to more than one region.
+              If this is the case ``mask_3D`` correctly assigns them and ``mask``
+              raises an Error.
 
         Returns
         -------
@@ -512,7 +514,7 @@ class Regions:
             source = df.attrs.get("source")
 
         if overlap is None:
-            overlap = df.attrs.get("overlap", False)
+            overlap = df.attrs.get("overlap", None)
 
         return _from_geopandas(
             df,
diff --git a/regionmask/defined_regions/__init__.py b/regionmask/defined_regions/__init__.py
index 32a176d..c526f67 100644
--- a/regionmask/defined_regions/__init__.py
+++ b/regionmask/defined_regions/__init__.py
@@ -2,7 +2,21 @@
 
 from . import _natural_earth, _ressources
 from ._ar6 import ar6
-from ._natural_earth import natural_earth, natural_earth_v4_1_0, natural_earth_v5_0_0
+from ._natural_earth import natural_earth_v4_1_0, natural_earth_v5_0_0
 from .giorgi import giorgi
 from .prudence import prudence
 from .srex import srex
+
+
+def __getattr__(attr_name):
+    # TODO: remove in v0.14.0 or so (added in v0.12.0)
+
+    if attr_name == "natural_earth":
+        raise AttributeError(
+            "The `natural_earth` regions have been removed. Use ``natural_earth_v4_1_0`` "
+            " or ``natural_earth_v5_0_0`` instead."
+        )
+
+    raise AttributeError(
+        f"module 'regionmask.defined_regions' has no attribute '{attr_name}'"
+    )
diff --git a/regionmask/defined_regions/_natural_earth.py b/regionmask/defined_regions/_natural_earth.py
index 93b2751..aa0aa0d 100644
--- a/regionmask/defined_regions/_natural_earth.py
+++ b/regionmask/defined_regions/_natural_earth.py
@@ -1,6 +1,3 @@
-import os
-import warnings
-from abc import ABC, abstractmethod
 from contextlib import contextmanager
 from dataclasses import dataclass
 
@@ -20,13 +17,6 @@ try:
 except ImportError:
     engine = "fiona"
 
-# TODO: remove deprecated (v0.9.0) natural_earth class and instance & clean up
-
-ALTERNATIVE = (
-    "Please use ``regionmask.defined_regions.natural_earth_v4_1_0`` or "
-    "``regionmask.defined_regions.natural_earth_v5_0_0`` instead"
-)
-
 
 def _maybe_get_column(df, colname):
     """return column of the df or not"""
@@ -208,14 +198,16 @@ _ocean_basins_50 = _NaturalEarthFeature(
 )
 
 
-class NaturalEarth(ABC):
+class NaturalEarth:
     """class combining all natural_earth features/ geometries
 
     Because data must be downloaded, we organise it as a class so that
     we only download it on demand.
     """
 
-    def __init__(self):
+    def __init__(self, version, fix_ocean_basins_50):
+        self.version = version
+        self._fix_ocean_basins_50 = fix_ocean_basins_50
 
         self._countries_110 = None
         self._countries_50 = None
@@ -230,9 +222,9 @@ class NaturalEarth(ABC):
 
         self._ocean_basins_50 = None
 
-    @abstractmethod
     def _obtain_ne(self, natural_earth_feature, **kwargs):
-        ...
+        shapefilename = natural_earth_feature.shapefilename(self.version)
+        return _obtain_ne(shapefilename, **kwargs)
 
     @property
     def countries_110(self):
@@ -352,53 +344,28 @@ class NaturalEarth(ABC):
         return self._ocean_basins_50
 
     def __repr__(self):
-        return "Region Definitions from 'http://www.naturalearthdata.com'."
+        return f"Region definitions from 'http://www.naturalearthdata.com' - {self.version}"
 
 
-def _fix_ocean_basins_50_cartopy(self, df):
-    """ocean basins 50 has duplicate entries"""
+def _unify_great_barrier_reef(df, idx1, idx2):
 
-    names_v4_1_0 = {
-        14: "Mediterranean Sea",
-        30: "Mediterranean Sea",
-        26: "Ross Sea",
-        29: "Ross Sea",
-    }
-
-    names_v5_0_0 = {
-        74: "Great Barrier Reef",
-        114: "Great Barrier Reef",
-    }
-
-    names_v5_1_2 = {
-        74: "Great Barrier Reef",
-        113: "Great Barrier Reef",
-    }
-
-    is_v4_1_0 = all(df.loc[idx]["name"] == name for idx, name in names_v4_1_0.items())
-    is_v5_0_0 = all(df.loc[idx]["name"] == name for idx, name in names_v5_0_0.items())
-    is_v5_1_2 = all(df.loc[idx]["name"] == name for idx, name in names_v5_1_2.items())
+    p1 = df.loc[idx1].geometry
+    p2 = df.loc[idx2].geometry
 
-    if is_v4_1_0:
-        df = _fix_ocean_basins_50_v4_1_0(self, df)
-    elif is_v5_0_0:
-        df = _fix_ocean_basins_50_v5_0_0(self, df)
-    elif is_v5_1_2:
-        df = _fix_ocean_basins_50_v5_1_2(self, df)
-    else:
-        raise ValueError(
-            "Unknown version of the ocean basins 50m data from naturalearth. "
-            f"{ALTERNATIVE}."
-        )
+    # merge the two Great Barrier Reef polygons - idx1 <<< idx2
+    poly = p1.union(p2)
+    df.at[idx1, "geometry"] = poly
+    # remove the now merged row
+    df = df.drop(labels=idx2).reset_index()
 
     return df
 
 
-def _fix_ocean_basins_50_v4_1_0(self, df):
+def _fix_ocean_basins_50_v4_1_0(df):
     """fix ocean basins 50 for naturalearth v4.1.0
 
     - Mediterranean Sea and Ross Sea have two parts: renamed to Eastern and Western
-      Basin
+    Basin
     """
 
     new_names = {
@@ -415,21 +382,7 @@ def _fix_ocean_basins_50_v4_1_0(self, df):
     return df
 
 
-def _unify__great_barrier_reef(df, idx1, idx2):
-
-    p1 = df.loc[idx1].geometry
-    p2 = df.loc[idx2].geometry
-
-    # merge the two Great Barrier Reef polygons - idx1 <<< idx2
-    poly = p1.union(p2)
-    df.at[idx1, "geometry"] = poly
-    # remove the now merged row
-    df = df.drop(labels=idx2).reset_index()
-
-    return df
-
-
-def _fix_ocean_basins_50_v5_0_0(self, df):
+def _fix_ocean_basins_50_v5_0_0(df):
     """fix ocean basins 50 for naturalearth v5.0.0
 
     - Mediterranean Sea and Ross Sea is **no longer** split in two.
@@ -437,95 +390,11 @@ def _fix_ocean_basins_50_v5_0_0(self, df):
     - The numbers/ indices are different from Version 4.0!
     """
 
-    return _unify__great_barrier_reef(df, 74, 114)
-
-
-def _fix_ocean_basins_50_v5_1_2(self, df):
-    """fix ocean basins 50 for naturalearth v5.1.2
-
-    - Sea of Japan & Korea Strait geometries are different
-    - the rest (including the split of the Great Barrier Reef) is as in v5.0.0
-    - but the regions are ordered different
-    """
-
-    return _unify__great_barrier_reef(df, 74, 113)
+    return _unify_great_barrier_reef(df, 74, 114)
 
 
-class NaturalEarthCartopy(NaturalEarth):
-
-    _fix_ocean_basins_50 = _fix_ocean_basins_50_cartopy
-
-    def _obtain_ne(self, natural_earth_feature, **kwargs):
-
-        shapefilename = _get_shapefilename_cartopy(
-            natural_earth_feature.resolution,
-            natural_earth_feature.category,
-            natural_earth_feature.name,
-        )
-
-        return _obtain_ne(shapefilename, **kwargs)
-
-
-class NaturalEarth_v4_1_0(NaturalEarth):
-
-    _fix_ocean_basins_50 = _fix_ocean_basins_50_v4_1_0
-    version = "v4.1.0"
-
-    def _obtain_ne(self, natural_earth_feature, **kwargs):
-        shapefilename = natural_earth_feature.shapefilename(self.version)
-        return _obtain_ne(shapefilename, **kwargs)
-
-
-class NaturalEarth_v5_0_0(NaturalEarth):
-
-    _fix_ocean_basins_50 = _fix_ocean_basins_50_v5_0_0
-    version = "v5.0.0"
-
-    def _obtain_ne(self, natural_earth_feature, **kwargs):
-        shapefilename = natural_earth_feature.shapefilename(self.version)
-        return _obtain_ne(shapefilename, **kwargs)
-
-
-natural_earth = NaturalEarthCartopy()
-
-natural_earth_v4_1_0 = NaturalEarth_v4_1_0()
-natural_earth_v5_0_0 = NaturalEarth_v5_0_0()
-
-
-def _get_shapefilename_cartopy(resolution, category, name):
-
-    try:
-        import cartopy
-    except ImportError as e:
-        msg = (
-            "``regionmask.defined_regions.natural_earth`` requires cartopy and is "
-            f"deprecated.\n{ALTERNATIVE} (which do not require cartopy)."
-        )
-        raise ImportError(msg) from e
-
-    _cartopy_data_dir = cartopy.config["data_dir"]
-
-    # check if cartopy has already downloaded the file
-    cartopy_file = os.path.join(
-        _cartopy_data_dir,
-        "shapefiles",
-        "natural_earth",
-        f"{category}",
-        f"ne_{resolution}_{name}.shp",
-    )
-
-    if not os.path.exists(cartopy_file):
-        raise ValueError(
-            "``regionmask.defined_regions.natural_earth`` is deprecated. Will not "
-            f"download new files via this interface. {ALTERNATIVE}."
-        )
-
-    warnings.warn(
-        f"``regionmask.defined_regions.natural_earth`` is deprecated. {ALTERNATIVE}.",
-        FutureWarning,
-    )
-
-    return cartopy_file
+natural_earth_v4_1_0 = NaturalEarth("v4.1.0", _fix_ocean_basins_50_v4_1_0)
+natural_earth_v5_0_0 = NaturalEarth("v5.0.0", _fix_ocean_basins_50_v5_0_0)
 
 
 @contextmanager


Test patch:
diff --git a/regionmask/tests/test_Regions.py b/regionmask/tests/test_Regions.py
index 24a6c60..4aae512 100644
--- a/regionmask/tests/test_Regions.py
+++ b/regionmask/tests/test_Regions.py
@@ -420,10 +420,11 @@ def test_from_geodataframe():
     r = Regions.from_geodataframe(df)
     assert r.name == "unnamed"
     assert r.source is None
-    assert r.overlap is False
+    assert r.overlap is None
 
 
-def test_from_geodataframe_roundtrip():
+@pytest.mark.parametrize("overlap", [True, False, None])
+def test_from_geodataframe_roundtrip(overlap):
 
     import geopandas
 
@@ -431,7 +432,7 @@ def test_from_geodataframe_roundtrip():
 
     df = geopandas.GeoDataFrame(data=data, geometry=[poly1, poly2], index=numbers2)
     df.index.name = "numbers"
-    df.attrs = dict(source="source", name=name, overlap=True)
+    df.attrs = dict(source="source", name=name, overlap=overlap)
 
     r = Regions.from_geodataframe(df)
 
diff --git a/regionmask/tests/test_defined_regions.py b/regionmask/tests/test_defined_regions.py
index e82ebb1..22164c6 100644
--- a/regionmask/tests/test_defined_regions.py
+++ b/regionmask/tests/test_defined_regions.py
@@ -1,18 +1,13 @@
-import os
 from operator import attrgetter
 
 import numpy as np
 import pytest
 
 from regionmask import Regions, defined_regions
-from regionmask.defined_regions._natural_earth import _maybe_get_column
+from regionmask.defined_regions._natural_earth import NaturalEarth, _maybe_get_column
 
-from . import has_cartopy, requires_cartopy
-from .utils import (
-    REGIONS_ALL,
-    REGIONS_REQUIRING_CARTOPY,
-    download_naturalearth_region_or_skip,
-)
+from . import requires_cartopy
+from .utils import REGIONS_ALL
 
 
 def _test_region(defined_region):
@@ -37,53 +32,41 @@ def test_defined_region(defined_region):
     _test_region(defined_region)
 
 
-@requires_cartopy
-@pytest.mark.filterwarnings("ignore:Downloading")
-@pytest.mark.parametrize("defined_region", REGIONS_REQUIRING_CARTOPY, ids=str)
-def test_defined_regions_natural_earth(monkeypatch, defined_region):
-    # TODO: remove this test once defined_regions.natural_earth is removed
+def test_defined_regions_natural_earth_informative_error():
 
-    import cartopy
+    with pytest.raises(
+        AttributeError, match="The `natural_earth` regions have been removed."
+    ):
+        defined_regions.natural_earth
 
-    from regionmask.defined_regions import _natural_earth
 
-    match = "``regionmask.defined_regions.natural_earth`` is deprecated"
+def test_defined_regions_attribute_error():
 
-    # get regionmask.defined_regions._natural_earth._land_10 dataclass
-    region = defined_region.region_name.split(".")[1]
-    natural_earth_feature = attrgetter(f"_{region}")(_natural_earth)
+    with pytest.raises(
+        AttributeError,
+        match="module 'regionmask.defined_regions' has no attribute 'attr'",
+    ):
+        defined_regions.attr
 
-    # get the filename of cartopy-downloaded shapefiles
-    resolution = natural_earth_feature.resolution
-    category = natural_earth_feature.category
-    name = natural_earth_feature.name
 
-    _cartopy_data_dir = cartopy.config["data_dir"]
+def test_natural_earth_wrong_version():
+    ne_wrong_version = NaturalEarth("v0.3.0", None)
 
-    # check if cartopy has already downloaded the file
-    cartopy_file = os.path.join(
-        _cartopy_data_dir,
-        "shapefiles",
-        "natural_earth",
-        f"{category}",
-        f"ne_{resolution}_{name}.shp",
-    )
+    with pytest.raises(ValueError, match="version must"):
+        ne_wrong_version.land_110
 
-    # only raise an error if the file is not downloaded
-    if not os.path.isfile(cartopy_file):
-        with pytest.raises(ValueError, match=match):
-            attrgetter(defined_region.region_name)(defined_regions)
 
-    # download data using cartopy
-    download_naturalearth_region_or_skip(monkeypatch, natural_earth_feature)
+def test_natural_earth_repr():
+    actual = repr(defined_regions.natural_earth_v4_1_0)
+    expected = "Region definitions from 'http://www.naturalearthdata.com' - v4.1.0"
+    assert actual == expected
 
-    # get region and ensure deprcation warning is raised
-    with pytest.warns(FutureWarning, match=match):
-        _test_region(defined_region)
+    actual = repr(defined_regions.natural_earth_v5_0_0)
+    expected = "Region definitions from 'http://www.naturalearthdata.com' - v5.0.0"
+    assert actual == expected
 
 
 def test_fix_ocean_basins_50():
-
     region = defined_regions.natural_earth_v4_1_0.ocean_basins_50
     assert "Mediterranean Sea Eastern Basin" in region.names
     assert "Ross Sea Eastern Basin" in region.names
@@ -119,10 +102,3 @@ def test_maybe_get_column():
 
     with pytest.raises(KeyError, match="not on the geopandas dataframe"):
         _maybe_get_column(lowercase, "not_a_column")
-
-
-@pytest.mark.skipif(has_cartopy, reason="should run if cartopy is _not_ installed")
-def test_natural_earth_raises_without_cartopy():
-
-    with pytest.raises(ImportError, match="requires cartopy"):
-        defined_regions.natural_earth.countries_110
diff --git a/regionmask/tests/test_geopandas.py b/regionmask/tests/test_geopandas.py
index a06f5a9..5eb1b66 100644
--- a/regionmask/tests/test_geopandas.py
+++ b/regionmask/tests/test_geopandas.py
@@ -106,6 +106,7 @@ def test_from_geopandas_use_columns(geodataframe_clean):
     assert result.abbrevs == ["uSq1", "uSq2", "uSq3"]
     assert result.name == "name"
     assert result.source == "source"
+    assert result.overlap is None
 
 
 @pytest.mark.parametrize("attr", ["name", "source", "overlap"])
@@ -133,7 +134,10 @@ def test_from_geopandas_default(geodataframe_clean):
     assert result.names == ["Region0", "Region1", "Region2"]
     assert result.abbrevs == ["r0", "r1", "r2"]
     assert result.name == "unnamed"
-    assert result.source is None
+    assert result.overlap is None
+
+    result = from_geopandas(geodataframe_clean, overlap=True)
+    assert result.overlap is True
 
 
 @pytest.mark.parametrize("arg", ["names", "abbrevs", "numbers"])
diff --git a/regionmask/tests/utils.py b/regionmask/tests/utils.py
index fd065fb..429eaf9 100644
--- a/regionmask/tests/utils.py
+++ b/regionmask/tests/utils.py
@@ -1,10 +1,7 @@
-import warnings
 from dataclasses import dataclass
-from functools import partial
 from typing import Optional
 
 import numpy as np
-import pytest
 import xarray as xr
 
 from regionmask import Regions
@@ -157,36 +154,3 @@ REGIONS += _REGIONS_NATURAL_EARTH_v5_0_0
 
 REGIONS_ALL = REGIONS.copy()
 REGIONS_ALL += _REGIONS_NATURAL_EARTH_v4_1_0
-
-REGIONS_REQUIRING_CARTOPY = [
-    DefinedRegion("natural_earth.countries_110", 177),
-    DefinedRegion("natural_earth.countries_50", 242),
-    DefinedRegion("natural_earth.us_states_50", 51),
-    DefinedRegion("natural_earth.us_states_10", 51),
-    DefinedRegion("natural_earth.land_110", 1),
-    DefinedRegion("natural_earth.land_50", 1),
-    DefinedRegion("natural_earth.land_10", 1),
-    DefinedRegion("natural_earth.ocean_basins_50", 117),
-]
-
-
-def download_naturalearth_region_or_skip(monkeypatch, natural_earth_feature):
-
-    from urllib.request import URLError, urlopen
-
-    import cartopy
-    from cartopy.io import shapereader
-
-    # add a timeout to cartopy.io.urlopen else it can run indefinitely
-    monkeypatch.setattr(cartopy.io, "urlopen", partial(urlopen, timeout=5))
-
-    try:
-        shapereader.natural_earth(
-            natural_earth_feature.resolution,
-            natural_earth_feature.category,
-            natural_earth_feature.name,
-        )
-    except URLError as e:
-        warnings.warn(str(e))
-        warnings.warn("naturalearth download timeout - test not run!")
-        pytest.skip()