Files
california-equity-git/.venv/lib/python3.12/site-packages/geopandas/tests/test_crs.py
2025-01-26 19:24:23 -08:00

748 lines
26 KiB
Python

import random
import warnings
import numpy as np
import pandas as pd
from shapely.geometry import LineString, Point, Polygon
from geopandas import GeoDataFrame, GeoSeries, points_from_xy, read_file
from geopandas.array import GeometryArray, from_shapely, from_wkb, from_wkt
import pytest
from geopandas.testing import assert_geodataframe_equal
pyproj = pytest.importorskip("pyproj")
def _create_df(x, y=None, crs=None):
y = y or x
x = np.asarray(x)
y = np.asarray(y)
return GeoDataFrame(
{"geometry": points_from_xy(x, y), "value1": x + y, "value2": x * y}, crs=crs
)
def df_epsg26918():
# EPSG:26918
# Center coordinates
# -1683723.64 6689139.23
return _create_df(
x=range(-1683723, -1683723 + 10, 1),
y=range(6689139, 6689139 + 10, 1),
crs="epsg:26918",
)
def test_to_crs_transform():
df = df_epsg26918()
lonlat = df.to_crs(epsg=4326)
utm = lonlat.to_crs(epsg=26918)
assert_geodataframe_equal(df, utm, check_less_precise=True)
def test_to_crs_transform__missing_data():
# https://github.com/geopandas/geopandas/issues/1573
df = df_epsg26918()
df.loc[3, "geometry"] = None
lonlat = df.to_crs(epsg=4326)
utm = lonlat.to_crs(epsg=26918)
assert_geodataframe_equal(df, utm, check_less_precise=True)
def test_to_crs_transform__empty_data():
df = df_epsg26918().iloc[:0]
lonlat = df.to_crs(epsg=4326)
utm = lonlat.to_crs(epsg=26918)
assert_geodataframe_equal(df, utm, check_less_precise=True)
def test_to_crs_inplace():
df = df_epsg26918()
lonlat = df.to_crs(epsg=4326)
df.to_crs(epsg=4326, inplace=True)
assert_geodataframe_equal(df, lonlat, check_less_precise=True)
def test_to_crs_geo_column_name():
# Test to_crs() with different geometry column name (GH#339)
df = df_epsg26918()
df = df.rename(columns={"geometry": "geom"})
df.set_geometry("geom", inplace=True)
lonlat = df.to_crs(epsg=4326)
utm = lonlat.to_crs(epsg=26918)
assert lonlat.geometry.name == "geom"
assert utm.geometry.name == "geom"
assert_geodataframe_equal(df, utm, check_less_precise=True)
def test_to_crs_dimension_z():
# preserve z dimension
arr = points_from_xy([1, 2], [2, 3], [3, 4], crs=4326)
assert arr.has_z.all()
result = arr.to_crs(epsg=3857)
assert result.has_z.all()
# pyproj + numpy 1.25 trigger warning for single-element array -> recommdation is to
# ignore the warning for now (https://github.com/pyproj4/pyproj/issues/1307)
@pytest.mark.filterwarnings("ignore:Conversion of an array with:DeprecationWarning")
def test_to_crs_dimension_mixed():
s = GeoSeries([Point(1, 2), LineString([(1, 2, 3), (4, 5, 6)])], crs=2056)
result = s.to_crs(epsg=4326)
assert not result[0].is_empty
assert result.has_z.tolist() == [False, True]
roundtrip = result.to_crs(epsg=2056)
# TODO replace with assert_geoseries_equal once we expose tolerance keyword
# assert_geoseries_equal(roundtrip, s, check_less_precise=True)
for a, b in zip(roundtrip, s):
np.testing.assert_allclose(a.coords[:], b.coords[:], atol=0.01)
# -----------------------------------------------------------------------------
# Test different supported formats for CRS specification
@pytest.fixture(
params=[
4326,
"epsg:4326",
pytest.param(
{"init": "epsg:4326"},
),
"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs",
{"proj": "latlong", "ellps": "WGS84", "datum": "WGS84", "no_defs": True},
],
ids=["epsg_number", "epsg_string", "epsg_dict", "proj4_string", "proj4_dict"],
)
def epsg4326(request):
if isinstance(request.param, int):
return {"epsg": request.param}
return {"crs": request.param}
@pytest.fixture(
params=[
26918,
"epsg:26918",
pytest.param(
{"init": "epsg:26918", "no_defs": True},
),
"+proj=utm +zone=18 +ellps=GRS80 +datum=NAD83 +units=m +no_defs ",
{"proj": "utm", "zone": 18, "datum": "NAD83", "units": "m", "no_defs": True},
],
ids=["epsg_number", "epsg_string", "epsg_dict", "proj4_string", "proj4_dict"],
)
def epsg26918(request):
if isinstance(request.param, int):
return {"epsg": request.param}
return {"crs": request.param}
@pytest.mark.filterwarnings("ignore:'\\+init:DeprecationWarning")
@pytest.mark.filterwarnings("ignore:'\\+init:FutureWarning")
def test_transform2(epsg4326, epsg26918):
# with PROJ >= 7, the transformation using EPSG code vs proj4 string is
# slightly different due to use of grid files or not -> turn off network
# to not use grid files at all for this test
pyproj.network.set_network_enabled(False)
df = df_epsg26918()
lonlat = df.to_crs(**epsg4326)
utm = lonlat.to_crs(**epsg26918)
# can't check for CRS equality, as the formats differ although representing
# the same CRS
assert_geodataframe_equal(df, utm, check_less_precise=True, check_crs=False)
# pyproj + numpy 1.25 trigger warning for single-element array -> recommdation is to
# ignore the warning for now (https://github.com/pyproj4/pyproj/issues/1307)
@pytest.mark.filterwarnings("ignore:Conversion of an array with:DeprecationWarning")
def test_crs_axis_order__always_xy():
df = GeoDataFrame(geometry=[Point(-1683723, 6689139)], crs="epsg:26918")
lonlat = df.to_crs("epsg:4326")
test_lonlat = GeoDataFrame(
geometry=[Point(-110.1399901, 55.1350011)], crs="epsg:4326"
)
assert_geodataframe_equal(lonlat, test_lonlat, check_less_precise=True)
def test_skip_exact_same():
df = df_epsg26918()
utm = df.to_crs(df.crs)
assert_geodataframe_equal(df, utm, check_less_precise=True)
# Test CRS on GeometryArray level
class TestGeometryArrayCRS:
def setup_method(self):
self.osgb = pyproj.CRS(27700)
self.wgs = pyproj.CRS(4326)
self.geoms = [Point(0, 0), Point(1, 1)]
self.polys = [
Polygon([(random.random(), random.random()) for i in range(3)])
for _ in range(10)
]
self.arr = from_shapely(self.polys, crs=27700)
def test_array(self):
arr = from_shapely(self.geoms)
arr.crs = 27700
assert arr.crs == self.osgb
arr = from_shapely(self.geoms, crs=27700)
assert arr.crs == self.osgb
arr = GeometryArray(arr)
assert arr.crs == self.osgb
arr = GeometryArray(arr, crs=4326)
assert arr.crs == self.wgs
def test_series(self):
s = GeoSeries(crs=27700)
assert s.crs == self.osgb
assert s.values.crs == self.osgb
arr = from_shapely(self.geoms)
s = GeoSeries(arr, crs=27700)
assert s.crs == self.osgb
assert s.values.crs == self.osgb
# manually change CRS
s = s.set_crs(4326, allow_override=True)
assert s.crs == self.wgs
assert s.values.crs == self.wgs
s = GeoSeries(self.geoms, crs=27700)
assert s.crs == self.osgb
assert s.values.crs == self.osgb
arr = from_shapely(self.geoms, crs=27700)
s = GeoSeries(arr)
assert s.crs == self.osgb
assert s.values.crs == self.osgb
with pytest.raises(
ValueError,
match="CRS mismatch between CRS of the passed geometries and 'crs'",
):
s = GeoSeries(arr, crs=4326)
assert s.crs == self.osgb
def test_dataframe(self):
arr = from_shapely(self.geoms, crs=27700)
df = GeoDataFrame(geometry=arr)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
arr = from_shapely(self.geoms)
s = GeoSeries(arr, crs=27700)
df = GeoDataFrame(geometry=s)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
# different passed CRS than array CRS is now an error
match_str = "CRS mismatch between CRS of the passed geometries and 'crs'"
with pytest.raises(ValueError, match=match_str):
df = GeoDataFrame(geometry=s, crs=4326)
with pytest.raises(ValueError, match=match_str):
GeoDataFrame(geometry=s, crs=4326)
with pytest.raises(ValueError, match=match_str):
GeoDataFrame({"data": [1, 2], "geometry": s}, crs=4326)
with pytest.raises(ValueError, match=match_str):
GeoDataFrame(df, crs=4326).crs
# manually change CRS
arr = from_shapely(self.geoms)
s = GeoSeries(arr, crs=27700)
df = GeoDataFrame(geometry=s)
df = df.set_crs(crs="epsg:4326", allow_override=True)
assert df.crs == self.wgs
assert df.geometry.crs == self.wgs
assert df.geometry.values.crs == self.wgs
with pytest.raises(ValueError, match="Assigning CRS to a GeoDataFrame without"):
GeoDataFrame(self.geoms, columns=["geom"], crs=27700)
with pytest.raises(ValueError, match="Assigning CRS to a GeoDataFrame without"):
GeoDataFrame(crs=27700)
df = GeoDataFrame(self.geoms, columns=["geom"])
df = df.set_geometry("geom", crs=27700)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
assert df.geom.crs == self.osgb
assert df.geom.values.crs == self.osgb
df = GeoDataFrame(geometry=self.geoms, crs=27700)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
# new geometry with set CRS has priority over GDF CRS
df = GeoDataFrame(geometry=self.geoms, crs=27700)
df = df.set_geometry(self.geoms, crs=4326)
assert df.crs == self.wgs
assert df.geometry.crs == self.wgs
assert df.geometry.values.crs == self.wgs
arr = from_shapely(self.geoms)
s = GeoSeries(arr, crs=27700)
df = GeoDataFrame()
df = df.set_geometry(s)
assert df._geometry_column_name == "geometry"
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
arr = from_shapely(self.geoms, crs=27700)
df = GeoDataFrame()
df = df.set_geometry(arr)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
arr = from_shapely(self.geoms)
df = GeoDataFrame({"col1": [1, 2], "geometry": arr}, crs=4326)
assert df.crs == self.wgs
assert df.geometry.crs == self.wgs
assert df.geometry.values.crs == self.wgs
arr = from_shapely(self.geoms, crs=4326)
df = GeoDataFrame({"col1": [1, 2], "geometry": arr})
assert df.crs == self.wgs
assert df.geometry.crs == self.wgs
assert df.geometry.values.crs == self.wgs
# geometry column name None on init
df = GeoDataFrame({"geometry": [0, 1]})
with pytest.raises(
ValueError,
match="Assigning CRS to a GeoDataFrame without a geometry",
):
df.crs = 27700
# geometry column without geometry
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore", "Geometry column does not contain geometry", UserWarning
)
df = GeoDataFrame({"geometry": [Point(0, 1)]}).assign(geometry=[0])
with pytest.raises(
ValueError,
match="Assigning CRS to a GeoDataFrame without an active geometry",
):
df.crs = 27700
with pytest.raises(
AttributeError,
match="The CRS attribute of a GeoDataFrame without an active",
):
assert df.crs == self.osgb
def test_dataframe_getitem_without_geometry_column(self):
df = GeoDataFrame({"col": range(10)}, geometry=self.arr)
df["geom2"] = df.geometry.centroid
subset = df[["col", "geom2"]]
with pytest.raises(
AttributeError,
match="The CRS attribute of a GeoDataFrame without an active",
):
assert subset.crs == self.osgb
def test_dataframe_setitem(self):
# new geometry CRS has priority over GDF CRS
arr = from_shapely(self.geoms)
s = GeoSeries(arr, crs=27700)
df = GeoDataFrame()
with pytest.warns(
FutureWarning, match="You are adding a column named 'geometry'"
):
df["geometry"] = s
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
arr = from_shapely(self.geoms, crs=27700)
df = GeoDataFrame()
with pytest.warns(
FutureWarning, match="You are adding a column named 'geometry'"
):
df["geometry"] = arr
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
# test to_crs case (GH1960)
arr = from_shapely(self.geoms)
df = GeoDataFrame({"col1": [1, 2], "geometry": arr}, crs=4326)
df["geometry"] = df["geometry"].to_crs(27700)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
# test changing geometry crs not in the geometry column doesn't change the crs
arr = from_shapely(self.geoms)
df = GeoDataFrame(
{"col1": [1, 2], "geometry": arr, "other_geom": arr}, crs=4326
)
df["other_geom"] = from_shapely(self.geoms, crs=27700)
assert df.crs == self.wgs
assert df.geometry.crs == self.wgs
assert df["geometry"].crs == self.wgs
assert df["other_geom"].crs == self.osgb
def test_dataframe_setitem_without_geometry_column(self):
arr = from_shapely(self.geoms)
df = GeoDataFrame({"col1": [1, 2], "geometry": arr}, crs=4326)
# override geometry with non geometry
with pytest.warns(UserWarning):
df["geometry"] = 1
# assigning a list of geometry object doesn't have cached access to 4326
df["geometry"] = self.geoms
assert df.crs is None
@pytest.mark.parametrize(
"scalar", [None, Point(0, 0), LineString([(0, 0), (1, 1)])]
)
def test_scalar(self, scalar):
df = GeoDataFrame()
with pytest.warns(
FutureWarning, match="You are adding a column named 'geometry'"
):
df["geometry"] = scalar
df = df.set_crs(4326)
assert df.crs == self.wgs
assert df.geometry.crs == self.wgs
assert df.geometry.values.crs == self.wgs
@pytest.mark.filterwarnings("ignore:Accessing CRS")
def test_crs_with_no_geom_fails(self):
with pytest.raises(ValueError, match="Assigning CRS to a GeoDataFrame without"):
df = GeoDataFrame()
df.crs = 4326
def test_read_file(self, nybb_filename):
df = read_file(nybb_filename)
assert df.crs == pyproj.CRS(2263)
assert df.geometry.crs == pyproj.CRS(2263)
assert df.geometry.values.crs == pyproj.CRS(2263)
def test_multiple_geoms(self):
arr = from_shapely(self.geoms, crs=27700)
s = GeoSeries(self.geoms, crs=4326)
df = GeoDataFrame(s, geometry=arr, columns=["col1"])
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
assert df.col1.crs == self.wgs
assert df.col1.values.crs == self.wgs
def test_multiple_geoms_set_geom(self):
arr = from_shapely(self.geoms, crs=27700)
s = GeoSeries(self.geoms, crs=4326)
df = GeoDataFrame(s, geometry=arr, columns=["col1"])
df = df.set_geometry("col1")
assert df.crs == self.wgs
assert df.geometry.crs == self.wgs
assert df.geometry.values.crs == self.wgs
assert df["geometry"].crs == self.osgb
assert df["geometry"].values.crs == self.osgb
def test_assign_cols(self):
arr = from_shapely(self.geoms, crs=27700)
s = GeoSeries(self.geoms, crs=4326)
df = GeoDataFrame(s, geometry=arr, columns=["col1"])
df["geom2"] = s
df["geom3"] = s.values
df["geom4"] = from_shapely(self.geoms)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
assert df.geom2.crs == self.wgs
assert df.geom2.values.crs == self.wgs
assert df.geom3.crs == self.wgs
assert df.geom3.values.crs == self.wgs
assert df.geom4.crs is None
assert df.geom4.values.crs is None
def test_copy(self):
arr = from_shapely(self.geoms, crs=27700)
s = GeoSeries(self.geoms, crs=4326)
df = GeoDataFrame(s, geometry=arr, columns=["col1"])
arr_copy = arr.copy()
assert arr_copy.crs == arr.crs
s_copy = s.copy()
assert s_copy.crs == s.crs
assert s_copy.values.crs == s.values.crs
df_copy = df.copy()
assert df_copy.crs == df.crs
assert df_copy.geometry.crs == df.geometry.crs
assert df_copy.geometry.values.crs == df.geometry.values.crs
assert df_copy.col1.crs == df.col1.crs
assert df_copy.col1.values.crs == df.col1.values.crs
def test_rename(self):
arr = from_shapely(self.geoms, crs=27700)
s = GeoSeries(self.geoms, crs=4326)
df = GeoDataFrame(s, geometry=arr, columns=["col1"])
df = df.rename(columns={"geometry": "geom"}).set_geometry("geom")
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
df = df.rename_geometry("geom2")
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
df = df.rename(columns={"col1": "column1"})
assert df.column1.crs == self.wgs
assert df.column1.values.crs == self.wgs
def test_geoseries_to_crs(self):
s = GeoSeries(self.geoms, crs=27700)
s = s.to_crs(4326)
assert s.crs == self.wgs
assert s.values.crs == self.wgs
df = GeoDataFrame(geometry=s)
assert df.crs == self.wgs
df = df.to_crs(27700)
assert df.crs == self.osgb
assert df.geometry.crs == self.osgb
assert df.geometry.values.crs == self.osgb
# make sure that only active geometry is transformed
arr = from_shapely(self.geoms, crs=4326)
df["col1"] = arr
df = df.to_crs(3857)
assert df.col1.crs == self.wgs
assert df.col1.values.crs == self.wgs
def test_array_to_crs(self):
arr = from_shapely(self.geoms, crs=27700)
arr = arr.to_crs(4326)
assert arr.crs == self.wgs
def test_from_shapely(self):
arr = from_shapely(self.geoms, crs=27700)
assert arr.crs == self.osgb
def test_from_wkb(self):
L_wkb = [p.wkb for p in self.geoms]
arr = from_wkb(L_wkb, crs=27700)
assert arr.crs == self.osgb
def test_from_wkt(self):
L_wkt = [p.wkt for p in self.geoms]
arr = from_wkt(L_wkt, crs=27700)
assert arr.crs == self.osgb
def test_points_from_xy(self):
df = pd.DataFrame([{"x": x, "y": x, "z": x} for x in range(10)])
arr = points_from_xy(df["x"], df["y"], crs=27700)
assert arr.crs == self.osgb
# setting CRS in GeoSeries should not set it in passed array without CRS
def test_original(self):
arr = from_shapely(self.geoms)
s = GeoSeries(arr, crs=27700)
assert arr.crs is None
assert s.crs == self.osgb
def test_ops(self):
arr = self.arr
bound = arr.boundary
assert bound.crs == self.osgb
cent = arr.centroid
assert cent.crs == self.osgb
hull = arr.convex_hull
assert hull.crs == self.osgb
envelope = arr.envelope
assert envelope.crs == self.osgb
exterior = arr.exterior
assert exterior.crs == self.osgb
representative_point = arr.representative_point()
assert representative_point.crs == self.osgb
def test_binary_ops(self):
arr = self.arr
quads = []
while len(quads) < 10:
geom = Polygon([(random.random(), random.random()) for i in range(4)])
if geom.is_valid:
quads.append(geom)
arr2 = from_shapely(quads, crs=27700)
difference = arr.difference(arr2)
assert difference.crs == self.osgb
intersection = arr.intersection(arr2)
assert intersection.crs == self.osgb
symmetric_difference = arr.symmetric_difference(arr2)
assert symmetric_difference.crs == self.osgb
union = arr.union(arr2)
assert union.crs == self.osgb
def test_other(self):
arr = self.arr
buffer = arr.buffer(5)
assert buffer.crs == self.osgb
interpolate = arr.exterior.interpolate(0.1)
assert interpolate.crs == self.osgb
simplify = arr.simplify(5)
assert simplify.crs == self.osgb
@pytest.mark.parametrize(
"attr, arg",
[
("affine_transform", ([0, 1, 1, 0, 0, 0],)),
("translate", ()),
("rotate", (10,)),
("scale", ()),
("skew", ()),
],
)
def test_affinity_methods(self, attr, arg):
result = getattr(self.arr, attr)(*arg)
assert result.crs == self.osgb
def test_slice(self):
s = GeoSeries(self.arr, crs=27700)
assert s.iloc[1:].values.crs == self.osgb
df = GeoDataFrame({"col1": self.arr}, geometry=s)
assert df.iloc[1:].geometry.values.crs == self.osgb
assert df.iloc[1:].col1.values.crs == self.osgb
def test_concat(self):
s = GeoSeries(self.arr, crs=27700)
assert pd.concat([s, s]).values.crs == self.osgb
df = GeoDataFrame({"col1": from_shapely(self.geoms, crs=4326)}, geometry=s)
assert pd.concat([df, df]).geometry.values.crs == self.osgb
assert pd.concat([df, df]).col1.values.crs == self.wgs
def test_merge(self):
arr = from_shapely(self.geoms, crs=27700)
s = GeoSeries(self.geoms, crs=4326)
df = GeoDataFrame({"col1": s}, geometry=arr)
df2 = GeoDataFrame({"col2": s}, geometry=arr).rename_geometry("geom")
merged = df.merge(df2, left_index=True, right_index=True)
assert merged.col1.values.crs == self.wgs
assert merged.geometry.values.crs == self.osgb
assert merged.col2.values.crs == self.wgs
assert merged.geom.values.crs == self.osgb
assert merged.crs == self.osgb
# make sure that geometry column from list has CRS (__setitem__)
def test_setitem_geometry(self):
arr = from_shapely(self.geoms, crs=27700)
df = GeoDataFrame({"col1": [0, 1]}, geometry=arr)
df["geometry"] = list(df.geometry)
assert df.geometry.values.crs == self.osgb
df2 = GeoDataFrame({"col1": [0, 1]}, geometry=arr)
df2["geometry"] = from_shapely(self.geoms, crs=4326)
assert df2.geometry.values.crs == self.wgs
def test_astype(self):
arr = from_shapely(self.geoms, crs=27700)
df = GeoDataFrame({"col1": [0, 1]}, geometry=arr)
df2 = df.astype({"col1": str})
assert df2.crs == self.osgb
def test_apply(self):
s = GeoSeries(self.arr)
assert s.crs == 27700
# apply preserves the CRS if the result is a GeoSeries
result = s.apply(lambda x: x.centroid)
assert result.crs == 27700
def test_apply_geodataframe(self):
df = GeoDataFrame({"col1": [0, 1]}, geometry=self.geoms, crs=27700)
assert df.crs == 27700
# apply preserves the CRS if the result is a GeoDataFrame
result = df.apply(lambda col: col, axis=0)
assert result.crs == 27700
result = df.apply(lambda row: row, axis=1)
assert result.crs == 27700
class TestSetCRS:
@pytest.mark.parametrize(
"constructor",
[
lambda geoms, crs: GeoSeries(geoms, crs=crs),
lambda geoms, crs: GeoDataFrame(geometry=geoms, crs=crs),
],
ids=["geoseries", "geodataframe"],
)
def test_set_crs(self, constructor):
naive = constructor([Point(0, 0), Point(1, 1)], crs=None)
assert naive.crs is None
# by default returns a copy
result = naive.set_crs(crs="EPSG:4326")
assert result.crs == "EPSG:4326"
assert naive.crs is None
result = naive.set_crs(epsg=4326)
assert result.crs == "EPSG:4326"
assert naive.crs is None
# with inplace=True
result = naive.set_crs(crs="EPSG:4326", inplace=True)
assert result is naive
assert result.crs == naive.crs == "EPSG:4326"
# raise for non-naive when crs would be overridden
non_naive = constructor([Point(0, 0), Point(1, 1)], crs="EPSG:4326")
assert non_naive.crs == "EPSG:4326"
with pytest.raises(ValueError, match="already has a CRS"):
non_naive.set_crs("EPSG:3857")
# allow for equal crs
result = non_naive.set_crs("EPSG:4326")
assert result.crs == "EPSG:4326"
# replace with allow_override=True
result = non_naive.set_crs("EPSG:3857", allow_override=True)
assert non_naive.crs == "EPSG:4326"
assert result.crs == "EPSG:3857"
result = non_naive.set_crs("EPSG:3857", allow_override=True, inplace=True)
assert non_naive.crs == "EPSG:3857"
assert result.crs == "EPSG:3857"
# set CRS to None
result = non_naive.set_crs(crs=None, allow_override=True)
assert result.crs is None
assert non_naive.crs == "EPSG:3857"