Repository: geopandas/geopandas

Issue:
BUG: CRS not propagated to array
I have found one issue caused by #1339. OSMnx [uses](https://github.com/gboeing/osmnx/blob/a4b4dc9efb8223b8aab257ff8825454d4bd06ddc/osmnx/projection.py#L71-L75) following pattern:

```py
geometry = Point(0,0)  # my addition

gdf = gpd.GeoDataFrame()
gdf.crs = 4326
gdf['geometry'] = None
gdf.loc[0, 'geometry'] = geometry
...
gdf.to_crs()  # it fails here due to missing CRS
```

In the end, gdf does have CRS but `geometry` and GeometryArray do not. It just raises two warnings:

```
FutureWarning: Assigning CRS to a GeoDataFrame without a geometry column is now deprecated and will not be supported in the future.

UserWarning: Geometry column does not contain geometry.
```

I would say that we should fix that now, but it is not a pattern I would encourage at all.


Discussion:
That's indeed a pattern we want to discourage ;)

I suppose the problem is that `gdf.loc[0, 'geometry'] = geometry` directly involves setting values in the GeometryArray (if there would be one, see below), without going through a GeoDataFrame method (like `__getitem__`) where we can "fix" this to set the gdf's crs. 

> gdf['geometry'] = None
> UserWarning: Geometry column does not contain geometry.

I suppose we can fix this case to ensure that we create an empty GeometryArray here (instead of raising the warning en letting pandas create an empty object dtype column). 
If we then also directly set the gdf's crs, I think that should also solve the above issue.

Resolving patch:
diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py
--- a/geopandas/geodataframe.py
+++ b/geopandas/geodataframe.py
@@ -6,6 +6,8 @@
 from pandas import DataFrame, Series
 
 from shapely.geometry import mapping, shape
+from shapely.geometry.base import BaseGeometry
+
 
 from pyproj import CRS
 
@@ -684,6 +686,8 @@ def __setitem__(self, key, value):
         df['geometry'] = [geom... for geom in df.geometry]
         """
         if not pd.api.types.is_list_like(key) and key == self._geometry_column_name:
+            if pd.api.types.is_scalar(value) or isinstance(value, BaseGeometry):
+                value = [value] * self.shape[0]
             try:
                 value = _ensure_geometry(value, crs=self.crs)
             except TypeError:


Test patch:
diff --git a/geopandas/tests/test_crs.py b/geopandas/tests/test_crs.py
--- a/geopandas/tests/test_crs.py
+++ b/geopandas/tests/test_crs.py
@@ -6,7 +6,7 @@
 import numpy as np
 import pandas as pd
 
-from shapely.geometry import Point, Polygon
+from shapely.geometry import Point, Polygon, LineString
 import pyproj
 
 from geopandas import GeoSeries, GeoDataFrame, points_from_xy, datasets, read_file
@@ -282,6 +282,18 @@ def test_dataframe(self):
         df.crs = 27700
         assert df.crs == self.osgb
 
+    @pytest.mark.parametrize(
+        "scalar", [None, Point(0, 0), LineString([(0, 0), (1, 1)])]
+    )
+    def test_scalar(self, scalar):
+        with pytest.warns(FutureWarning):
+            df = GeoDataFrame()
+            df.crs = 4326
+        df["geometry"] = scalar
+        assert df.crs == self.wgs
+        assert df.geometry.crs == self.wgs
+        assert df.geometry.values.crs == self.wgs
+
     def test_read_file(self):
         nybb_filename = datasets.get_path("nybb")
         df = read_file(nybb_filename)