11import os
22import pathlib
33
4- import geoarrow .pyarrow as ga
4+ import duckdb
5+ import geoarrow .pyarrow as ga # noqa: F401
56import humanize
67import ibis
78import leafmap .foliumap as leafmap
8- import obstore .fsspec
99import pyarrow as pa
10- import pyarrow .parquet as pq
1110import streamlit as st
12- from geoarrow .pyarrow .io import read_geoparquet_table
1311from obstore .store import S3Store
1412from omegaconf import OmegaConf
1513from pyogrio import read_info
1614
1715
16+ @st .cache_data
1817def load_config ():
1918 """Load config from config.yaml or S3_EXPLORER_CONFIG env var."""
2019 config_path = pathlib .Path (
@@ -25,6 +24,7 @@ def load_config():
2524 return OmegaConf .create ({"buckets" : {}})
2625
2726
27+ @st .cache_resource
2828def create_store (
2929 bucket_name : str , endpoint : str , access_key : str | None , secret_key : str | None
3030) -> S3Store :
@@ -45,22 +45,7 @@ def create_store(
4545 )
4646
4747
48- def create_fs (
49- bucket_name : str , endpoint : str , access_key : str | None , secret_key : str | None
50- ) -> obstore .fsspec .FsspecStore :
51- """Create an fsspec filesystem for the given bucket."""
52- config = {
53- "endpoint" : endpoint ,
54- }
55- if access_key :
56- config ["access_key_id" ] = access_key
57- config ["secret_access_key" ] = secret_key
58- else :
59- config ["skip_signature" ] = True
60- return obstore .fsspec .FsspecStore ("s3" , ** config )
61-
62-
63- @st .cache_data ()
48+ @st .cache_data
6449def load_bucket_contents (
6550 bucket_name : str , endpoint : str , access_key : str | None , secret_key : str | None
6651) -> pa .Table | None :
@@ -91,7 +76,7 @@ def load_bucket_contents(
9176 return None
9277
9378
94- @st .cache_resource
79+ @st .cache_data
9580def load_file_content (
9681 bucket_name : str ,
9782 endpoint : str ,
@@ -109,14 +94,6 @@ def preview_file(bucket_cfg, bucket_name: str, path: str):
10994 ext = pathlib .Path (path ).suffix .lower ()
11095
11196 http_path = f"{ bucket_cfg .endpoint } /{ bucket_cfg .bucket } /{ path } "
112- fs = create_fs (
113- bucket_cfg .bucket or bucket_name ,
114- bucket_cfg .endpoint ,
115- bucket_cfg .get ("access_key" ),
116- bucket_cfg .get ("secret_key" ),
117- )
118-
119- s3_path = f"s3://{ bucket_name } /{ path } "
12097
12198 try :
12299 if ext in (".png" , ".jpg" , ".jpeg" , ".gif" , ".webp" , ".svg" ):
@@ -146,26 +123,27 @@ def preview_file(bucket_cfg, bucket_name: str, path: str):
146123 with st .expander ("Show file metadata (PyOGRIO)" ):
147124 st .json (info )
148125
126+ con = duckdb .connect ()
127+ con .execute ("set memory_limit = '1GB'" )
128+ df = con .read_parquet (http_path ).limit (2000 )
129+
149130 if info ["crs" ]:
150131 try :
151- with fs .open (s3_path , "rb" ) as f :
152- gdf = ga .to_geopandas (read_geoparquet_table (f )).head (2000 )
153-
132+ df = ga .to_geopandas (df .arrow ())
154133 st .warning ("Only the first 2000 elements are previewed" )
155134 m = leafmap .Map ()
156- geom_only = gdf [[ gdf .geometry .name ]]
135+ geom_only = df [[ df .geometry .name ]]
157136 m .add_gdf (geom_only , layer_name = "Geometries" )
158- st .dataframe (gdf , width = "stretch" , height = 400 )
137+ st .dataframe (df , width = "stretch" , height = 400 )
159138 try :
160139 m .to_streamlit ()
161140 except Exception as e :
162141 st .warning (f"Could not render map preview: { e } " )
163142 except Exception as e :
164143 st .warning (f"Could not render as geospatial data: { e } " )
165144 else :
166- with fs .open (s3_path , "rb" ) as f :
167- table = pq .read_table (f )
168- st .dataframe (table , width = "stretch" , height = 400 )
145+ st .dataframe (df , width = "stretch" , height = 400 )
146+ con .close ()
169147
170148 elif ext in (".txt" , ".md" , ".json" , ".yaml" , ".yml" , ".csv" , ".xml" ):
171149 content = load_file_content (
0 commit comments