1
1
use crate :: error:: { PyGeoArrowError , PyGeoArrowResult } ;
2
- use crate :: io:: file:: { BinaryFileReader , BinaryFileWriter } ;
2
+ use crate :: io:: input:: sync:: BinaryFileWriter ;
3
+ use crate :: io:: input:: { construct_reader, FileReader } ;
3
4
use crate :: io:: object_store:: PyObjectStore ;
4
5
use crate :: table:: GeoTable ;
5
6
use flatgeobuf:: FgbWriterOptions ;
6
7
use geoarrow:: io:: flatgeobuf:: read_flatgeobuf_async as _read_flatgeobuf_async;
7
8
use geoarrow:: io:: flatgeobuf:: write_flatgeobuf_with_options as _write_flatgeobuf;
8
9
use geoarrow:: io:: flatgeobuf:: { read_flatgeobuf as _read_flatgeobuf, FlatGeobufReaderOptions } ;
10
+ use pyo3:: exceptions:: PyValueError ;
9
11
use pyo3:: prelude:: * ;
10
12
11
- /// Read a FlatGeobuf file from a path on disk into a GeoTable.
13
+ /// Read a FlatGeobuf file from a path on disk or a remote location into a GeoTable.
12
14
///
13
15
/// Example:
14
16
///
15
- /// Reading a remote file on an S3 bucket.
17
+ /// Reading from a local path:
16
18
///
17
19
/// ```py
18
- /// from geoarrow.rust.core import ObjectStore, read_flatgeobuf_async
20
+ /// from geoarrow.rust.core import read_flatgeobuf
21
+ /// table = read_flatgeobuf("path/to/file.fgb")
22
+ /// ```
23
+ ///
24
+ /// Reading from a Python file object:
25
+ ///
26
+ /// ```py
27
+ /// from geoarrow.rust.core import read_flatgeobuf
28
+ ///
29
+ /// with open("path/to/file.fgb", "rb") as file:
30
+ /// table = read_flatgeobuf(file)
31
+ /// ```
32
+ ///
33
+ /// Reading from an HTTP(S) url:
34
+ ///
35
+ /// ```py
36
+ /// from geoarrow.rust.core import read_flatgeobuf
37
+ ///
38
+ /// url = "http://flatgeobuf.org/test/data/UScounties.fgb"
39
+ /// table = read_flatgeobuf(url)
40
+ /// ```
41
+ ///
42
+ /// Reading from a remote file on an S3 bucket.
43
+ ///
44
+ /// ```py
45
+ /// from geoarrow.rust.core import ObjectStore, read_flatgeobuf
19
46
///
20
47
/// options = {
21
48
/// "aws_access_key_id": "...",
22
49
/// "aws_secret_access_key": "...",
23
50
/// "aws_region": "..."
24
51
/// }
25
52
/// fs = ObjectStore('s3://bucket', options=options)
26
- /// table = read_flatgeobuf("path/in/bucket.fgb", fs)
53
+ /// table = read_flatgeobuf("path/in/bucket.fgb", fs=fs )
27
54
/// ```
28
55
///
29
56
/// Args:
@@ -47,80 +74,102 @@ pub fn read_flatgeobuf(
47
74
batch_size : usize ,
48
75
bbox : Option < ( f64 , f64 , f64 , f64 ) > ,
49
76
) -> PyGeoArrowResult < GeoTable > {
50
- if let Some ( fs) = fs {
51
- fs. rt . block_on ( async move {
77
+ let reader = construct_reader ( py, file, fs) ?;
78
+ match reader {
79
+ FileReader :: Async ( async_reader) => async_reader. runtime . block_on ( async move {
52
80
let options = FlatGeobufReaderOptions {
53
81
batch_size : Some ( batch_size) ,
54
82
bbox,
55
83
..Default :: default ( )
56
84
} ;
57
- let path = file. extract :: < String > ( py) ?;
58
- let table = _read_flatgeobuf_async ( fs. inner , path. into ( ) , options)
85
+ let table = _read_flatgeobuf_async ( async_reader. store , async_reader. path , options)
59
86
. await
60
87
. map_err ( PyGeoArrowError :: GeoArrowError ) ?;
61
88
62
89
Ok ( GeoTable ( table) )
63
- } )
64
- } else {
65
- let mut reader = file . extract :: < BinaryFileReader > ( py ) ? ;
66
- let options = FlatGeobufReaderOptions {
67
- batch_size : Some ( batch_size ) ,
68
- bbox ,
69
- .. Default :: default ( )
70
- } ;
71
- let table = _read_flatgeobuf ( & mut reader , options ) ? ;
72
- Ok ( GeoTable ( table ) )
90
+ } ) ,
91
+ FileReader :: Sync ( mut sync_reader ) => {
92
+ let options = FlatGeobufReaderOptions {
93
+ batch_size : Some ( batch_size ) ,
94
+ bbox ,
95
+ .. Default :: default ( )
96
+ } ;
97
+ let table = _read_flatgeobuf ( & mut sync_reader , options ) ? ;
98
+ Ok ( GeoTable ( table ) )
99
+ }
73
100
}
74
101
}
75
102
76
103
/// Read a FlatGeobuf file from a url into a GeoTable.
77
104
///
78
105
/// Example:
79
106
///
80
- /// ```py
81
- /// from geoarrow.rust.core import ObjectStore, read_flatgeobuf_async
107
+ /// Reading from an HTTP(S) url:
108
+ ///
109
+ /// ```py
110
+ /// from geoarrow.rust.core import read_flatgeobuf_async
111
+ ///
112
+ /// url = "http://flatgeobuf.org/test/data/UScounties.fgb"
113
+ /// table = await read_flatgeobuf_async(url)
114
+ /// ```
82
115
///
83
- /// options = {
84
- /// "aws_access_key_id": "...",
85
- /// "aws_secret_access_key": "...",
86
- /// }
87
- /// fs = ObjectStore('s3://bucket', options=options)
88
- /// table = await read_flatgeobuf_async("path/in/bucket.fgb", fs)
89
- /// ```
116
+ /// Reading from an S3 bucket:
117
+ ///
118
+ /// ```py
119
+ /// from geoarrow.rust.core import ObjectStore, read_flatgeobuf_async
120
+ ///
121
+ /// options = {
122
+ /// "aws_access_key_id": "...",
123
+ /// "aws_secret_access_key": "...",
124
+ /// "aws_region": "..."
125
+ /// }
126
+ /// fs = ObjectStore('s3://bucket', options=options)
127
+ /// table = await read_flatgeobuf_async("path/in/bucket.fgb", fs=fs)
128
+ /// ```
90
129
///
91
130
/// Args:
92
- /// url: the url to a remote FlatGeobuf file
93
- /// fs: an ObjectStore instance for this url.
131
+ /// path: the url or relative path to a remote FlatGeobuf file. If an argument is passed for
132
+ /// `fs`, this should be a path fragment relative to the root passed to the `ObjectStore`
133
+ /// constructor.
94
134
///
95
135
/// Other args:
136
+ /// fs: an ObjectStore instance for this url. This is required for non-HTTP urls.
96
137
/// batch_size: the number of rows to include in each internal batch of the table.
97
138
/// bbox: A spatial filter for reading rows, of the format (minx, miny, maxx, maxy). If set to
98
139
/// `None`, no spatial filtering will be performed.
99
140
///
100
141
/// Returns:
101
142
/// Table from FlatGeobuf file.
102
143
#[ pyfunction]
103
- #[ pyo3( signature = ( path, fs , * , batch_size=65536 , bbox=None ) ) ]
144
+ #[ pyo3( signature = ( path, * , fs= None , batch_size=65536 , bbox=None ) ) ]
104
145
pub fn read_flatgeobuf_async (
105
146
py : Python ,
106
- path : String ,
107
- fs : PyObjectStore ,
147
+ path : PyObject ,
148
+ fs : Option < PyObjectStore > ,
108
149
batch_size : usize ,
109
150
bbox : Option < ( f64 , f64 , f64 , f64 ) > ,
110
151
) -> PyGeoArrowResult < PyObject > {
111
- let fut = pyo3_asyncio:: tokio:: future_into_py ( py, async move {
112
- let options = FlatGeobufReaderOptions {
113
- batch_size : Some ( batch_size) ,
114
- bbox,
115
- ..Default :: default ( )
116
- } ;
117
- let table = _read_flatgeobuf_async ( fs. inner , path. into ( ) , options)
118
- . await
119
- . map_err ( PyGeoArrowError :: GeoArrowError ) ?;
152
+ let reader = construct_reader ( py, path, fs) ?;
153
+ match reader {
154
+ FileReader :: Async ( async_reader) => {
155
+ let fut = pyo3_asyncio:: tokio:: future_into_py ( py, async move {
156
+ let options = FlatGeobufReaderOptions {
157
+ batch_size : Some ( batch_size) ,
158
+ bbox,
159
+ ..Default :: default ( )
160
+ } ;
161
+ let table = _read_flatgeobuf_async ( async_reader. store , async_reader. path , options)
162
+ . await
163
+ . map_err ( PyGeoArrowError :: GeoArrowError ) ?;
120
164
121
- Ok ( GeoTable ( table) )
122
- } ) ?;
123
- Ok ( fut. into ( ) )
165
+ Ok ( GeoTable ( table) )
166
+ } ) ?;
167
+ Ok ( fut. into ( ) )
168
+ }
169
+ FileReader :: Sync ( _) => {
170
+ Err ( PyValueError :: new_err ( "Local file paths not supported in async reader." ) . into ( ) )
171
+ }
172
+ }
124
173
}
125
174
126
175
/// Write a GeoTable to a FlatGeobuf file on disk.
0 commit comments