Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions eolearn/core/eodata_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
import gzip
import itertools
import json
import os
import platform
import shutil
import sys
import tempfile
import warnings
from abc import ABCMeta, abstractmethod
from collections import defaultdict
Expand Down Expand Up @@ -651,13 +654,17 @@ def _get_uncompressed_file_extension(cls) -> str:
return ".gpkg"

def _read_from_file(self, file: BinaryIO | gzip.GzipFile) -> gpd.GeoDataFrame:
dataframe = gpd.read_file(file)
# pyogrio (geopandas >= 1) warns when reading GPKG from virtual in-memory
# files without a .gpkg extension. Suppress this warning as it's harmless.
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message=".*GPKG application_id.*", category=RuntimeWarning)
dataframe = gpd.read_file(file)

if dataframe.crs is not None:
# Trying to preserve a standard CRS and passing otherwise
with contextlib.suppress(ValueError), warnings.catch_warnings():
warnings.simplefilter("ignore", category=SHUserWarning)
dataframe.crs = CRS(dataframe.crs).pyproj_crs()
dataframe = dataframe.set_crs(CRS(dataframe.crs).pyproj_crs())

if TIMESTAMP_COLUMN in dataframe:
dataframe[TIMESTAMP_COLUMN] = pd.to_datetime(dataframe[TIMESTAMP_COLUMN])
Expand All @@ -675,6 +682,34 @@ def _write_to_file(cls, data: gpd.GeoDataFrame, file: BinaryIO | gzip.GzipFile,
)
return data.to_file(file, driver="GPKG", encoding="utf-8", layer=layer, index=False)

@classmethod
def _save(cls, data: gpd.GeoDataFrame, filesystem: FS, path: str, compress_level: int) -> None:
"""Save GeoDataFrame, handling pyogrio (geopandas >= 1) which requires a real file path
for GPKG format and cannot write to open file handles or gzip-wrapped file objects.

This overrides the parent's _save to first write to a temporary .gpkg file, then
copy (and optionally gzip-compress) the content to the target filesystem.
"""
layer = fs.path.basename(path)
with tempfile.TemporaryDirectory() as tmp_dir:
tmp_gpkg = os.path.join(tmp_dir, "feature.gpkg")
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
message="You are attempting to write an empty DataFrame to file*",
category=UserWarning,
)
data.to_file(tmp_gpkg, driver="GPKG", encoding="utf-8", layer=layer, index=False)

if compress_level == 0:
with open(tmp_gpkg, "rb") as gpkg_file:
filesystem.writebytes(path, gpkg_file.read())
else:
with filesystem.openbin(path, "w") as file:
with gzip.GzipFile(fileobj=file, compresslevel=compress_level, mode="wb") as gzip_file:
with open(tmp_gpkg, "rb") as gpkg_file:
shutil.copyfileobj(gpkg_file, gzip_file)


class FeatureIOJson(FeatureIOGZip[T]):
"""FeatureIO object specialized for JSON-like objects."""
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ dependencies = [
"boto3",
"fs",
"fs-s3fs",
"geopandas>=0.14.4,<1; python_version>='3.9'",
"geopandas>=0.11.0,<1; python_version<'3.9'",
"geopandas>=0.14.4; python_version>='3.9'",
"geopandas>=0.11.0; python_version<'3.9'",
"numpy>=1.20.0",
"python-dateutil",
"sentinelhub>=3.9.0",
Expand Down