terrakio-core 0.4.3__py3-none-any.whl → 0.4.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of terrakio-core might be problematic. Click here for more details.
- terrakio_core/__init__.py +3 -1
- terrakio_core/accessors.py +477 -0
- terrakio_core/async_client.py +23 -38
- terrakio_core/client.py +83 -84
- terrakio_core/convenience_functions/convenience_functions.py +316 -324
- terrakio_core/endpoints/auth.py +8 -1
- terrakio_core/endpoints/mass_stats.py +13 -9
- terrakio_core/endpoints/model_management.py +604 -948
- terrakio_core/sync_client.py +341 -33
- {terrakio_core-0.4.3.dist-info → terrakio_core-0.4.4.dist-info}/METADATA +2 -1
- terrakio_core-0.4.4.dist-info/RECORD +22 -0
- terrakio_core-0.4.3.dist-info/RECORD +0 -21
- {terrakio_core-0.4.3.dist-info → terrakio_core-0.4.4.dist-info}/WHEEL +0 -0
- {terrakio_core-0.4.3.dist-info → terrakio_core-0.4.4.dist-info}/top_level.txt +0 -0
terrakio_core/sync_client.py
CHANGED
|
@@ -1,6 +1,345 @@
|
|
|
1
|
+
# import asyncio
|
|
2
|
+
# import concurrent.futures
|
|
3
|
+
# import threading
|
|
4
|
+
# import functools
|
|
5
|
+
# import inspect
|
|
6
|
+
# from typing import Optional, Dict, Any, Union
|
|
7
|
+
# from geopandas import GeoDataFrame
|
|
8
|
+
# from shapely.geometry.base import BaseGeometry as ShapelyGeometry
|
|
9
|
+
# from .async_client import AsyncClient
|
|
10
|
+
# from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
# # # Add this after your other imports
|
|
13
|
+
# # if TYPE_CHECKING:
|
|
14
|
+
# # from .endpoints.dataset_management import DatasetManagement
|
|
15
|
+
# # from .endpoints.user_management import UserManagement
|
|
16
|
+
# # from .endpoints.mass_stats import MassStats
|
|
17
|
+
# # from .endpoints.group_management import GroupManagement
|
|
18
|
+
# # from .endpoints.space_management import SpaceManagement
|
|
19
|
+
# # from .endpoints.model_management import ModelManagement
|
|
20
|
+
# # from .endpoints.auth import AuthClient
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# class SyncWrapper:
|
|
24
|
+
# """Generic synchronous wrapper with __dir__ support for runtime autocomplete."""
|
|
25
|
+
|
|
26
|
+
# def __init__(self, async_obj, sync_client):
|
|
27
|
+
# self._async_obj = async_obj
|
|
28
|
+
# self._sync_client = sync_client
|
|
29
|
+
|
|
30
|
+
# def __dir__(self):
|
|
31
|
+
# """Return list of attributes for autocomplete in interactive environments."""
|
|
32
|
+
# async_attrs = [attr for attr in dir(self._async_obj) if not attr.startswith('_')]
|
|
33
|
+
# wrapper_attrs = [attr for attr in object.__dir__(self) if not attr.startswith('_')]
|
|
34
|
+
# return list(set(async_attrs + wrapper_attrs))
|
|
35
|
+
|
|
36
|
+
# def __getattr__(self, name):
|
|
37
|
+
# """Dynamically wrap any method call to convert async to sync."""
|
|
38
|
+
# attr = getattr(self._async_obj, name)
|
|
39
|
+
|
|
40
|
+
# if callable(attr):
|
|
41
|
+
# @functools.wraps(attr)
|
|
42
|
+
# def sync_wrapper(*args, **kwargs):
|
|
43
|
+
# result = attr(*args, **kwargs)
|
|
44
|
+
# if hasattr(result, '__await__'):
|
|
45
|
+
# return self._sync_client._run_async(result)
|
|
46
|
+
# return result
|
|
47
|
+
# return sync_wrapper
|
|
48
|
+
|
|
49
|
+
# return attr
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# class SyncClient:
|
|
53
|
+
# """
|
|
54
|
+
# Thread-safe synchronous wrapper for AsyncClient.
|
|
55
|
+
# Uses a persistent event loop in a dedicated thread to avoid event loop conflicts.
|
|
56
|
+
# """
|
|
57
|
+
|
|
58
|
+
# # datasets: 'DatasetManagement'
|
|
59
|
+
# # users: 'UserManagement'
|
|
60
|
+
# # mass_stats: 'MassStats'
|
|
61
|
+
# # groups: 'GroupManagement'
|
|
62
|
+
# # space: 'SpaceManagement'
|
|
63
|
+
# # model: 'ModelManagement'
|
|
64
|
+
# # auth: 'AuthClient'
|
|
65
|
+
|
|
66
|
+
# def __init__(self, url: Optional[str] = None, api_key: Optional[str] = None, verbose: bool = False):
|
|
67
|
+
# self._async_client = AsyncClient(url=url, api_key=api_key, verbose=verbose)
|
|
68
|
+
# self._context_entered = False
|
|
69
|
+
# self._closed = False
|
|
70
|
+
|
|
71
|
+
# # Thread and event loop management
|
|
72
|
+
# self._loop = None
|
|
73
|
+
# self._thread = None
|
|
74
|
+
# self._loop_ready = None
|
|
75
|
+
# self._loop_exception = None
|
|
76
|
+
|
|
77
|
+
# # Initialize endpoint managers
|
|
78
|
+
# print("we are here!!!!!!!!!!!!!!!!!")
|
|
79
|
+
# self.datasets = SyncWrapper(self._async_client.datasets, self)
|
|
80
|
+
# self.users = SyncWrapper(self._async_client.users, self)
|
|
81
|
+
# self.mass_stats = SyncWrapper(self._async_client.mass_stats, self)
|
|
82
|
+
# self.groups = SyncWrapper(self._async_client.groups, self)
|
|
83
|
+
# self.space = SyncWrapper(self._async_client.space, self)
|
|
84
|
+
# self.model = SyncWrapper(self._async_client.model, self)
|
|
85
|
+
# self.auth = SyncWrapper(self._async_client.auth, self)
|
|
86
|
+
|
|
87
|
+
# # Register cleanup
|
|
88
|
+
# import atexit
|
|
89
|
+
# atexit.register(self._cleanup)
|
|
90
|
+
|
|
91
|
+
# def _ensure_event_loop(self):
|
|
92
|
+
# """Ensure we have a persistent event loop in a dedicated thread."""
|
|
93
|
+
# if self._loop is None or self._loop.is_closed():
|
|
94
|
+
# self._loop_ready = threading.Event()
|
|
95
|
+
# self._loop_exception = None
|
|
96
|
+
|
|
97
|
+
# def run_loop():
|
|
98
|
+
# """Run the event loop in a dedicated thread."""
|
|
99
|
+
# try:
|
|
100
|
+
# # Create a new event loop for this thread
|
|
101
|
+
# self._loop = asyncio.new_event_loop()
|
|
102
|
+
# asyncio.set_event_loop(self._loop)
|
|
103
|
+
|
|
104
|
+
# # Signal that the loop is ready
|
|
105
|
+
# self._loop_ready.set()
|
|
106
|
+
|
|
107
|
+
# # Run the loop forever (until stopped)
|
|
108
|
+
# self._loop.run_forever()
|
|
109
|
+
# except Exception as e:
|
|
110
|
+
# self._loop_exception = e
|
|
111
|
+
# self._loop_ready.set()
|
|
112
|
+
# finally:
|
|
113
|
+
# # Clean up when the loop stops
|
|
114
|
+
# if self._loop and not self._loop.is_closed():
|
|
115
|
+
# self._loop.close()
|
|
116
|
+
|
|
117
|
+
# # Start the thread
|
|
118
|
+
# self._thread = threading.Thread(target=run_loop, daemon=True)
|
|
119
|
+
# self._thread.start()
|
|
120
|
+
|
|
121
|
+
# # Wait for the loop to be ready
|
|
122
|
+
# self._loop_ready.wait(timeout=10)
|
|
123
|
+
|
|
124
|
+
# if self._loop_exception:
|
|
125
|
+
# raise self._loop_exception
|
|
126
|
+
|
|
127
|
+
# if not self._loop_ready.is_set():
|
|
128
|
+
# raise RuntimeError("Event loop failed to start within timeout")
|
|
129
|
+
|
|
130
|
+
# def _run_async(self, coro):
|
|
131
|
+
# """
|
|
132
|
+
# Run async coroutine using persistent event loop.
|
|
133
|
+
# This is the core method that makes everything work.
|
|
134
|
+
# """
|
|
135
|
+
# # Ensure we have an event loop
|
|
136
|
+
# self._ensure_event_loop()
|
|
137
|
+
|
|
138
|
+
# if self._loop.is_closed():
|
|
139
|
+
# raise RuntimeError("Event loop is closed")
|
|
140
|
+
|
|
141
|
+
# # Create a future to get the result back from the event loop thread
|
|
142
|
+
# future = concurrent.futures.Future()
|
|
143
|
+
|
|
144
|
+
# async def run_with_context():
|
|
145
|
+
# """Run the coroutine with proper context management."""
|
|
146
|
+
# try:
|
|
147
|
+
# # Ensure the async client is properly initialized
|
|
148
|
+
# await self._ensure_context()
|
|
149
|
+
|
|
150
|
+
# # Run the actual coroutine
|
|
151
|
+
# result = await coro
|
|
152
|
+
|
|
153
|
+
# # Set the result on the future
|
|
154
|
+
# future.set_result(result)
|
|
155
|
+
# except Exception as e:
|
|
156
|
+
# # Set the exception on the future
|
|
157
|
+
# future.set_exception(e)
|
|
158
|
+
|
|
159
|
+
# # Schedule the coroutine on the persistent event loop
|
|
160
|
+
# self._loop.call_soon_threadsafe(
|
|
161
|
+
# lambda: asyncio.create_task(run_with_context())
|
|
162
|
+
# )
|
|
163
|
+
|
|
164
|
+
# # Wait for the result (with timeout to avoid hanging)
|
|
165
|
+
# try:
|
|
166
|
+
# return future.result(timeout=300) # 5 minute timeout
|
|
167
|
+
# except concurrent.futures.TimeoutError:
|
|
168
|
+
# raise RuntimeError("Async operation timed out after 5 minutes")
|
|
169
|
+
|
|
170
|
+
# async def _ensure_context(self):
|
|
171
|
+
# """Ensure the async client context is entered."""
|
|
172
|
+
# if not self._context_entered and not self._closed:
|
|
173
|
+
# await self._async_client.__aenter__()
|
|
174
|
+
# self._context_entered = True
|
|
175
|
+
|
|
176
|
+
# async def _exit_context(self):
|
|
177
|
+
# """Exit the async client context."""
|
|
178
|
+
# if self._context_entered and not self._closed:
|
|
179
|
+
# await self._async_client.__aexit__(None, None, None)
|
|
180
|
+
# self._context_entered = False
|
|
181
|
+
|
|
182
|
+
# def close(self):
|
|
183
|
+
# """Close the underlying async client session and stop the event loop."""
|
|
184
|
+
# if not self._closed:
|
|
185
|
+
# if self._loop and not self._loop.is_closed():
|
|
186
|
+
# # Schedule cleanup on the event loop
|
|
187
|
+
# future = concurrent.futures.Future()
|
|
188
|
+
|
|
189
|
+
# async def cleanup():
|
|
190
|
+
# """Clean up the async client."""
|
|
191
|
+
# try:
|
|
192
|
+
# await self._exit_context()
|
|
193
|
+
# future.set_result(None)
|
|
194
|
+
# except Exception as e:
|
|
195
|
+
# future.set_exception(e)
|
|
196
|
+
|
|
197
|
+
# # Run cleanup
|
|
198
|
+
# self._loop.call_soon_threadsafe(
|
|
199
|
+
# lambda: asyncio.create_task(cleanup())
|
|
200
|
+
# )
|
|
201
|
+
|
|
202
|
+
# # Wait for cleanup to complete
|
|
203
|
+
# try:
|
|
204
|
+
# future.result(timeout=10)
|
|
205
|
+
# except:
|
|
206
|
+
# pass # Ignore cleanup errors
|
|
207
|
+
|
|
208
|
+
# # Stop the event loop
|
|
209
|
+
# self._loop.call_soon_threadsafe(self._loop.stop)
|
|
210
|
+
|
|
211
|
+
# # Wait for thread to finish
|
|
212
|
+
# if self._thread and self._thread.is_alive():
|
|
213
|
+
# self._thread.join(timeout=5)
|
|
214
|
+
|
|
215
|
+
# self._closed = True
|
|
216
|
+
|
|
217
|
+
# def _cleanup(self):
|
|
218
|
+
# """Internal cleanup method called by atexit."""
|
|
219
|
+
# if not self._closed:
|
|
220
|
+
# try:
|
|
221
|
+
# self.close()
|
|
222
|
+
# except Exception:
|
|
223
|
+
# pass # Ignore cleanup errors
|
|
224
|
+
|
|
225
|
+
# def __dir__(self):
|
|
226
|
+
# """Return list of attributes for autocomplete in interactive environments."""
|
|
227
|
+
# default_attrs = [attr for attr in object.__dir__(self) if not attr.startswith('_')]
|
|
228
|
+
# async_client_attrs = [attr for attr in dir(self._async_client) if not attr.startswith('_')]
|
|
229
|
+
# endpoint_attrs = ['datasets', 'users', 'mass_stats', 'groups', 'space', 'model', 'auth']
|
|
230
|
+
# all_attrs = default_attrs + async_client_attrs + endpoint_attrs
|
|
231
|
+
# return list(set(all_attrs))
|
|
232
|
+
|
|
233
|
+
# # Your existing methods (geoquery, zonal_stats, etc.)
|
|
234
|
+
# def geoquery(
|
|
235
|
+
# self,
|
|
236
|
+
# expr: str,
|
|
237
|
+
# feature: Union[Dict[str, Any], ShapelyGeometry],
|
|
238
|
+
# in_crs: str = "epsg:4326",
|
|
239
|
+
# out_crs: str = "epsg:4326",
|
|
240
|
+
# resolution: int = -1,
|
|
241
|
+
# geom_fix: bool = False,
|
|
242
|
+
# **kwargs
|
|
243
|
+
# ):
|
|
244
|
+
# """Compute WCS query for a single geometry (synchronous version)."""
|
|
245
|
+
# coro = self._async_client.geoquery(
|
|
246
|
+
# expr=expr,
|
|
247
|
+
# feature=feature,
|
|
248
|
+
# in_crs=in_crs,
|
|
249
|
+
# out_crs=out_crs,
|
|
250
|
+
# output="netcdf",
|
|
251
|
+
# resolution=resolution,
|
|
252
|
+
# geom_fix=geom_fix,
|
|
253
|
+
# **kwargs
|
|
254
|
+
# )
|
|
255
|
+
# return self._run_async(coro)
|
|
256
|
+
|
|
257
|
+
# def zonal_stats(
|
|
258
|
+
# self,
|
|
259
|
+
# gdf: GeoDataFrame,
|
|
260
|
+
# expr: str,
|
|
261
|
+
# conc: int = 20,
|
|
262
|
+
# inplace: bool = False,
|
|
263
|
+
# in_crs: str = "epsg:4326",
|
|
264
|
+
# out_crs: str = "epsg:4326",
|
|
265
|
+
# resolution: int = -1,
|
|
266
|
+
# geom_fix: bool = False,
|
|
267
|
+
# drop_nan: bool = False,
|
|
268
|
+
# spatial_reduction: str = None,
|
|
269
|
+
# temporal_reduction: str = None,
|
|
270
|
+
# max_memory_mb: int = 500,
|
|
271
|
+
# stream_to_disk: bool = False,
|
|
272
|
+
# ):
|
|
273
|
+
# """Compute zonal statistics for all geometries in a GeoDataFrame (synchronous version)."""
|
|
274
|
+
# coro = self._async_client.zonal_stats(
|
|
275
|
+
# gdf=gdf,
|
|
276
|
+
# expr=expr,
|
|
277
|
+
# conc=conc,
|
|
278
|
+
# inplace=inplace,
|
|
279
|
+
# in_crs=in_crs,
|
|
280
|
+
# out_crs=out_crs,
|
|
281
|
+
# resolution=resolution,
|
|
282
|
+
# geom_fix=geom_fix,
|
|
283
|
+
# drop_nan=drop_nan,
|
|
284
|
+
# spatial_reduction=spatial_reduction,
|
|
285
|
+
# temporal_reduction=temporal_reduction,
|
|
286
|
+
# max_memory_mb=max_memory_mb,
|
|
287
|
+
# stream_to_disk=stream_to_disk
|
|
288
|
+
# )
|
|
289
|
+
# return self._run_async(coro)
|
|
290
|
+
|
|
291
|
+
# def create_dataset_file(
|
|
292
|
+
# self,
|
|
293
|
+
# aoi: str,
|
|
294
|
+
# expression: str,
|
|
295
|
+
# output: str,
|
|
296
|
+
# in_crs: str = "epsg:4326",
|
|
297
|
+
# res: float = 0.0001,
|
|
298
|
+
# region: str = "aus",
|
|
299
|
+
# to_crs: str = "epsg:4326",
|
|
300
|
+
# overwrite: bool = True,
|
|
301
|
+
# skip_existing: bool = False,
|
|
302
|
+
# non_interactive: bool = True,
|
|
303
|
+
# poll_interval: int = 30,
|
|
304
|
+
# download_path: str = "/home/user/Downloads",
|
|
305
|
+
# ) -> dict:
|
|
306
|
+
# """Create a dataset file using mass stats operations (synchronous version)."""
|
|
307
|
+
# coro = self._async_client.create_dataset_file(
|
|
308
|
+
# aoi=aoi,
|
|
309
|
+
# expression=expression,
|
|
310
|
+
# output=output,
|
|
311
|
+
# in_crs=in_crs,
|
|
312
|
+
# res=res,
|
|
313
|
+
# region=region,
|
|
314
|
+
# to_crs=to_crs,
|
|
315
|
+
# overwrite=overwrite,
|
|
316
|
+
# skip_existing=skip_existing,
|
|
317
|
+
# non_interactive=non_interactive,
|
|
318
|
+
# poll_interval=poll_interval,
|
|
319
|
+
# download_path=download_path,
|
|
320
|
+
# )
|
|
321
|
+
# return self._run_async(coro)
|
|
322
|
+
|
|
323
|
+
# # Context manager support
|
|
324
|
+
# def __enter__(self):
|
|
325
|
+
# """Context manager entry."""
|
|
326
|
+
# return self
|
|
327
|
+
|
|
328
|
+
# def __exit__(self, exc_type, exc_val, exc_tb):
|
|
329
|
+
# """Context manager exit."""
|
|
330
|
+
# self.close()
|
|
331
|
+
|
|
332
|
+
# def __del__(self):
|
|
333
|
+
# """Destructor to ensure session is closed."""
|
|
334
|
+
# if not self._closed:
|
|
335
|
+
# try:
|
|
336
|
+
# self._cleanup()
|
|
337
|
+
# except Exception:
|
|
338
|
+
# pass
|
|
339
|
+
|
|
340
|
+
|
|
1
341
|
import asyncio
|
|
2
342
|
import functools
|
|
3
|
-
import inspect
|
|
4
343
|
from typing import Optional, Dict, Any, Union
|
|
5
344
|
from geopandas import GeoDataFrame
|
|
6
345
|
from shapely.geometry.base import BaseGeometry as ShapelyGeometry
|
|
@@ -21,13 +360,10 @@ class SyncWrapper:
|
|
|
21
360
|
Return list of attributes for autocomplete in interactive environments.
|
|
22
361
|
This enables autocomplete in Jupyter/iPython after instantiation.
|
|
23
362
|
"""
|
|
24
|
-
# Get all public attributes from the wrapped async object
|
|
25
363
|
async_attrs = [attr for attr in dir(self._async_obj) if not attr.startswith('_')]
|
|
26
364
|
|
|
27
|
-
# Get all attributes from this wrapper instance
|
|
28
365
|
wrapper_attrs = [attr for attr in object.__dir__(self) if not attr.startswith('_')]
|
|
29
366
|
|
|
30
|
-
# Combine and return unique attributes
|
|
31
367
|
return list(set(async_attrs + wrapper_attrs))
|
|
32
368
|
|
|
33
369
|
def __getattr__(self, name):
|
|
@@ -59,7 +395,6 @@ class SyncClient:
|
|
|
59
395
|
self._context_entered = False
|
|
60
396
|
self._closed = False
|
|
61
397
|
|
|
62
|
-
# Initialize endpoint managers
|
|
63
398
|
self.datasets = SyncWrapper(self._async_client.datasets, self)
|
|
64
399
|
self.users = SyncWrapper(self._async_client.users, self)
|
|
65
400
|
self.mass_stats = SyncWrapper(self._async_client.mass_stats, self)
|
|
@@ -68,7 +403,6 @@ class SyncClient:
|
|
|
68
403
|
self.model = SyncWrapper(self._async_client.model, self)
|
|
69
404
|
self.auth = SyncWrapper(self._async_client.auth, self)
|
|
70
405
|
|
|
71
|
-
# Register cleanup
|
|
72
406
|
import atexit
|
|
73
407
|
atexit.register(self._cleanup)
|
|
74
408
|
|
|
@@ -77,16 +411,12 @@ class SyncClient:
|
|
|
77
411
|
Return list of attributes for autocomplete in interactive environments.
|
|
78
412
|
This includes all methods from the async client plus the endpoint managers.
|
|
79
413
|
"""
|
|
80
|
-
# Get default attributes from this class
|
|
81
414
|
default_attrs = [attr for attr in object.__dir__(self) if not attr.startswith('_')]
|
|
82
415
|
|
|
83
|
-
# Get all public methods from the async client
|
|
84
416
|
async_client_attrs = [attr for attr in dir(self._async_client) if not attr.startswith('_')]
|
|
85
417
|
|
|
86
|
-
# Add endpoint managers
|
|
87
418
|
endpoint_attrs = ['datasets', 'users', 'mass_stats', 'groups', 'space', 'model', 'auth']
|
|
88
419
|
|
|
89
|
-
# Combine all attributes
|
|
90
420
|
all_attrs = default_attrs + async_client_attrs + endpoint_attrs
|
|
91
421
|
|
|
92
422
|
return list(set(all_attrs))
|
|
@@ -119,16 +449,10 @@ class SyncClient:
|
|
|
119
449
|
gdf: GeoDataFrame,
|
|
120
450
|
expr: str,
|
|
121
451
|
conc: int = 20,
|
|
122
|
-
inplace: bool = False,
|
|
123
452
|
in_crs: str = "epsg:4326",
|
|
124
453
|
out_crs: str = "epsg:4326",
|
|
125
454
|
resolution: int = -1,
|
|
126
455
|
geom_fix: bool = False,
|
|
127
|
-
drop_nan: bool = False,
|
|
128
|
-
spatial_reduction: str = None,
|
|
129
|
-
temporal_reduction: str = None,
|
|
130
|
-
max_memory_mb: int = 500,
|
|
131
|
-
stream_to_disk: bool = False,
|
|
132
456
|
):
|
|
133
457
|
"""
|
|
134
458
|
Compute zonal statistics for all geometries in a GeoDataFrame (synchronous version).
|
|
@@ -137,22 +461,13 @@ class SyncClient:
|
|
|
137
461
|
gdf (GeoDataFrame): GeoDataFrame containing geometries
|
|
138
462
|
expr (str): Terrakio expression to evaluate, can include spatial aggregations
|
|
139
463
|
conc (int): Number of concurrent requests to make
|
|
140
|
-
inplace (bool): Whether to modify the input GeoDataFrame in place
|
|
141
464
|
in_crs (str): Input coordinate reference system
|
|
142
465
|
out_crs (str): Output coordinate reference system
|
|
143
466
|
resolution (int): Resolution parameter
|
|
144
467
|
geom_fix (bool): Whether to fix the geometry (default False)
|
|
145
|
-
drop_nan (bool): Whether to drop NaN values from the results (default False)
|
|
146
|
-
spatial_reduction (str): Reduction operation for spatial dimensions (x, y).
|
|
147
|
-
Options: 'mean', 'median', 'min', 'max', 'std', 'var', 'sum', 'count'
|
|
148
|
-
temporal_reduction (str): Reduction operation for temporal dimension (time).
|
|
149
|
-
Options: 'mean', 'median', 'min', 'max', 'std', 'var', 'sum', 'count'
|
|
150
|
-
max_memory_mb (int): Maximum memory threshold in MB (default 500MB)
|
|
151
|
-
stream_to_disk (bool): Whether to stream datasets to disk as NetCDF files (default False)
|
|
152
468
|
|
|
153
469
|
Returns:
|
|
154
|
-
geopandas.GeoDataFrame: GeoDataFrame with added columns for results
|
|
155
|
-
If stream_to_disk=True, large datasets are saved as NetCDF files with file paths stored.
|
|
470
|
+
geopandas.GeoDataFrame: GeoDataFrame with added columns for results
|
|
156
471
|
|
|
157
472
|
Raises:
|
|
158
473
|
ValueError: If concurrency is too high or if data exceeds memory limit without streaming
|
|
@@ -162,16 +477,10 @@ class SyncClient:
|
|
|
162
477
|
gdf=gdf,
|
|
163
478
|
expr=expr,
|
|
164
479
|
conc=conc,
|
|
165
|
-
inplace=inplace,
|
|
166
480
|
in_crs=in_crs,
|
|
167
481
|
out_crs=out_crs,
|
|
168
482
|
resolution=resolution,
|
|
169
483
|
geom_fix=geom_fix,
|
|
170
|
-
drop_nan=drop_nan,
|
|
171
|
-
spatial_reduction=spatial_reduction,
|
|
172
|
-
temporal_reduction=temporal_reduction,
|
|
173
|
-
max_memory_mb=max_memory_mb,
|
|
174
|
-
stream_to_disk=stream_to_disk
|
|
175
484
|
)
|
|
176
485
|
return self._run_async(coro)
|
|
177
486
|
|
|
@@ -207,7 +516,6 @@ class SyncClient:
|
|
|
207
516
|
)
|
|
208
517
|
return self._run_async(coro)
|
|
209
518
|
|
|
210
|
-
# Rest of the methods remain the same...
|
|
211
519
|
async def _ensure_context(self):
|
|
212
520
|
"""Ensure the async client context is entered."""
|
|
213
521
|
if not self._context_entered and not self._closed:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: terrakio-core
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: Core components for Terrakio API clients
|
|
5
5
|
Author-email: Yupeng Chao <yupeng@haizea.com.au>
|
|
6
6
|
Project-URL: Homepage, https://github.com/HaizeaAnalytics/terrakio-python-api
|
|
@@ -24,6 +24,7 @@ Requires-Dist: geopandas>=0.13.0
|
|
|
24
24
|
Requires-Dist: google-cloud-storage>=2.0.0
|
|
25
25
|
Requires-Dist: scipy>=1.7.0
|
|
26
26
|
Requires-Dist: nest_asyncio
|
|
27
|
+
Requires-Dist: onnxruntime>=1.10.0
|
|
27
28
|
Provides-Extra: ml
|
|
28
29
|
Requires-Dist: torch>=2.7.1; extra == "ml"
|
|
29
30
|
Requires-Dist: scikit-learn>=1.7.0; extra == "ml"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
terrakio_core/__init__.py,sha256=tHjogyeQC-EKWpfPNnQqieQWGYRagVnj_LBiPP8vZrw,273
|
|
2
|
+
terrakio_core/accessors.py,sha256=qWLljU83YO7EUOefo_f6_P6ba6uiYMXwou0ihAHKBHQ,23706
|
|
3
|
+
terrakio_core/async_client.py,sha256=FYUuN1IboFkygylo0jFjEmhBGoHhzhAwG_KznkQR2y4,12449
|
|
4
|
+
terrakio_core/client.py,sha256=VXP7BtJWIfpPPZR7_yNdSTcGwNgTwhb7KorusqkQrzk,5603
|
|
5
|
+
terrakio_core/config.py,sha256=r8NARVYOca4AuM88VP_j-8wQxOk1s7VcRdyEdseBlLE,4193
|
|
6
|
+
terrakio_core/exceptions.py,sha256=4qnpOM1gOxsNIXDXY4qwY1d3I4Myhp7HBh7b2D0SVrU,529
|
|
7
|
+
terrakio_core/sync_client.py,sha256=HkLavfbT1sXGE1kTkiCDgNJxL9bErgOD6WihFrM-2xI,21873
|
|
8
|
+
terrakio_core/convenience_functions/convenience_functions.py,sha256=B7qbObjP4OuAUtrVf4Gi58c0q2EkTwOCOE568P0Q-EE,18607
|
|
9
|
+
terrakio_core/endpoints/auth.py,sha256=FdLsPScPIBo-Gxl6ZnE-46cp2molggAJtL72LssN3fg,6049
|
|
10
|
+
terrakio_core/endpoints/dataset_management.py,sha256=BUm8IIlW_Q45vDiQp16CiJGeSLheI8uWRVRQtMdhaNk,13161
|
|
11
|
+
terrakio_core/endpoints/group_management.py,sha256=VFl3jakjQa9OPi351D3DZvLU9M7fHdfjCzGhmyJsx3U,6309
|
|
12
|
+
terrakio_core/endpoints/mass_stats.py,sha256=6PSWWCpKLKMcFOoXfOAuROX8iSuG_dLyTYcw7gzhhZ4,23464
|
|
13
|
+
terrakio_core/endpoints/model_management.py,sha256=LH_gHPrqYA-_45KWpDBRcFbwHgm-Kg0zk1ealy7P_C0,52379
|
|
14
|
+
terrakio_core/endpoints/space_management.py,sha256=YWb55nkJnFJGlALJ520DvurxDqVqwYtsvqQPWzxzhDs,2266
|
|
15
|
+
terrakio_core/endpoints/user_management.py,sha256=WlFr3EfK8iI6DfkpMuYLHZUPk2n7_DHHO6z1hndmZB4,3816
|
|
16
|
+
terrakio_core/helper/bounded_taskgroup.py,sha256=wiTH10jhKZgrsgrFUNG6gig8bFkUEPHkGRT2XY7Rgmo,677
|
|
17
|
+
terrakio_core/helper/decorators.py,sha256=L6om7wmWNgCei3Wy5U0aZ-70OzsCwclkjIf7SfQuhCg,2289
|
|
18
|
+
terrakio_core/helper/tiles.py,sha256=xNtp3oDD912PN_FQV5fb6uQYhwfHANuXyIcxoVCCfZU,2632
|
|
19
|
+
terrakio_core-0.4.4.dist-info/METADATA,sha256=y2xrfAhs9JnlPKMyqj34QXXxS_AvY2tUyTrSM9SDFCY,1791
|
|
20
|
+
terrakio_core-0.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
terrakio_core-0.4.4.dist-info/top_level.txt,sha256=5cBj6O7rNWyn97ND4YuvvXm0Crv4RxttT4JZvNdOG6Q,14
|
|
22
|
+
terrakio_core-0.4.4.dist-info/RECORD,,
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
terrakio_core/__init__.py,sha256=GDUYT7cudfxltFZZ-2_5xM4Pd7o-pkQx1O8K9HrE5f0,248
|
|
2
|
-
terrakio_core/async_client.py,sha256=ffLKMbzclHfyBZBJn4uR8nlMW5E-96PX-4O5EghaSPE,13805
|
|
3
|
-
terrakio_core/client.py,sha256=-tGffOKGMyuowsvBwaV7Wtc_EZSWuSwv26_I5FkUank,5446
|
|
4
|
-
terrakio_core/config.py,sha256=r8NARVYOca4AuM88VP_j-8wQxOk1s7VcRdyEdseBlLE,4193
|
|
5
|
-
terrakio_core/exceptions.py,sha256=4qnpOM1gOxsNIXDXY4qwY1d3I4Myhp7HBh7b2D0SVrU,529
|
|
6
|
-
terrakio_core/sync_client.py,sha256=UpPn9rHp6x6otxj3QJ1Scnac4stgIpTtb__gmXszYCA,10787
|
|
7
|
-
terrakio_core/convenience_functions/convenience_functions.py,sha256=sBY2g7Vv3jakkuXnuFomXBWP0y6Q7q1K4ay3g4TxIoQ,21068
|
|
8
|
-
terrakio_core/endpoints/auth.py,sha256=e_hdNE6JOGhRVlQMFdEoOmoMHp5EzK6CclOEnc_AmZw,5863
|
|
9
|
-
terrakio_core/endpoints/dataset_management.py,sha256=BUm8IIlW_Q45vDiQp16CiJGeSLheI8uWRVRQtMdhaNk,13161
|
|
10
|
-
terrakio_core/endpoints/group_management.py,sha256=VFl3jakjQa9OPi351D3DZvLU9M7fHdfjCzGhmyJsx3U,6309
|
|
11
|
-
terrakio_core/endpoints/mass_stats.py,sha256=IZEozQ9GyOmUhd7V8M66Bz2OWsyq-VKzOw_sj_i-dng,23154
|
|
12
|
-
terrakio_core/endpoints/model_management.py,sha256=PF-2f6mW_RtkPWSL-N56kbgLeB6Z4EhU2N2qFqPan7o,70365
|
|
13
|
-
terrakio_core/endpoints/space_management.py,sha256=YWb55nkJnFJGlALJ520DvurxDqVqwYtsvqQPWzxzhDs,2266
|
|
14
|
-
terrakio_core/endpoints/user_management.py,sha256=WlFr3EfK8iI6DfkpMuYLHZUPk2n7_DHHO6z1hndmZB4,3816
|
|
15
|
-
terrakio_core/helper/bounded_taskgroup.py,sha256=wiTH10jhKZgrsgrFUNG6gig8bFkUEPHkGRT2XY7Rgmo,677
|
|
16
|
-
terrakio_core/helper/decorators.py,sha256=L6om7wmWNgCei3Wy5U0aZ-70OzsCwclkjIf7SfQuhCg,2289
|
|
17
|
-
terrakio_core/helper/tiles.py,sha256=xNtp3oDD912PN_FQV5fb6uQYhwfHANuXyIcxoVCCfZU,2632
|
|
18
|
-
terrakio_core-0.4.3.dist-info/METADATA,sha256=201kTjM26SSTmtRPBohs9GlBsP_3U3tUw6ja2X0D6uM,1756
|
|
19
|
-
terrakio_core-0.4.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
20
|
-
terrakio_core-0.4.3.dist-info/top_level.txt,sha256=5cBj6O7rNWyn97ND4YuvvXm0Crv4RxttT4JZvNdOG6Q,14
|
|
21
|
-
terrakio_core-0.4.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|