terrakio-core 0.4.4__py3-none-any.whl → 0.4.5__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 +1 -1
- terrakio_core/async_client.py +44 -1
- terrakio_core/sync_client.py +95 -11
- {terrakio_core-0.4.4.dist-info → terrakio_core-0.4.5.dist-info}/METADATA +1 -1
- {terrakio_core-0.4.4.dist-info → terrakio_core-0.4.5.dist-info}/RECORD +7 -7
- {terrakio_core-0.4.4.dist-info → terrakio_core-0.4.5.dist-info}/WHEEL +0 -0
- {terrakio_core-0.4.4.dist-info → terrakio_core-0.4.5.dist-info}/top_level.txt +0 -0
terrakio_core/__init__.py
CHANGED
terrakio_core/async_client.py
CHANGED
|
@@ -17,7 +17,7 @@ from .endpoints.group_management import GroupManagement
|
|
|
17
17
|
from .endpoints.space_management import SpaceManagement
|
|
18
18
|
from .endpoints.model_management import ModelManagement
|
|
19
19
|
from .endpoints.auth import AuthClient
|
|
20
|
-
from .convenience_functions.convenience_functions import zonal_stats as _zonal_stats, create_dataset_file as _create_dataset_file
|
|
20
|
+
from .convenience_functions.convenience_functions import zonal_stats as _zonal_stats, create_dataset_file as _create_dataset_file, request_geoquery_list as _request_geoquery_list
|
|
21
21
|
|
|
22
22
|
class AsyncClient(BaseClient):
|
|
23
23
|
def __init__(self, url: Optional[str] = None, api_key: Optional[str] = None, verbose: bool = False, session: Optional[aiohttp.ClientSession] = None):
|
|
@@ -282,6 +282,49 @@ class AsyncClient(BaseClient):
|
|
|
282
282
|
download_path=download_path,
|
|
283
283
|
)
|
|
284
284
|
|
|
285
|
+
async def geo_queries(
|
|
286
|
+
self,
|
|
287
|
+
queries: list[dict],
|
|
288
|
+
conc: int = 20,
|
|
289
|
+
):
|
|
290
|
+
"""
|
|
291
|
+
Execute multiple geo queries concurrently.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
queries (list[dict]): List of dictionaries containing query parameters.
|
|
295
|
+
Each query must have 'expr', 'feature', and 'in_crs' keys.
|
|
296
|
+
conc (int): Number of concurrent requests to make (default 20, max 100)
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
Union[float, geopandas.GeoDataFrame]:
|
|
300
|
+
- float: Average of all results if results are integers
|
|
301
|
+
- GeoDataFrame: GeoDataFrame with geometry and dataset columns if results are xarray datasets
|
|
302
|
+
|
|
303
|
+
Raises:
|
|
304
|
+
ValueError: If queries list is empty, concurrency is too high, or queries are malformed
|
|
305
|
+
APIError: If the API request fails
|
|
306
|
+
|
|
307
|
+
Example:
|
|
308
|
+
queries = [
|
|
309
|
+
{
|
|
310
|
+
'expr': 'WCF.wcf',
|
|
311
|
+
'feature': {'type': 'Feature', 'geometry': {...}, 'properties': {}},
|
|
312
|
+
'in_crs': 'epsg:4326'
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
'expr': 'NDVI.ndvi',
|
|
316
|
+
'feature': {'type': 'Feature', 'geometry': {...}, 'properties': {}},
|
|
317
|
+
'in_crs': 'epsg:4326'
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
result = await client.geo_queries(queries)
|
|
321
|
+
"""
|
|
322
|
+
return await _request_geoquery_list(
|
|
323
|
+
client=self,
|
|
324
|
+
quries=queries, # Note: keeping original parameter name for compatibility
|
|
325
|
+
conc=conc,
|
|
326
|
+
)
|
|
327
|
+
|
|
285
328
|
async def __aenter__(self):
|
|
286
329
|
if self._session is None:
|
|
287
330
|
headers = {
|
terrakio_core/sync_client.py
CHANGED
|
@@ -340,6 +340,7 @@
|
|
|
340
340
|
|
|
341
341
|
import asyncio
|
|
342
342
|
import functools
|
|
343
|
+
import concurrent.futures
|
|
343
344
|
from typing import Optional, Dict, Any, Union
|
|
344
345
|
from geopandas import GeoDataFrame
|
|
345
346
|
from shapely.geometry.base import BaseGeometry as ShapelyGeometry
|
|
@@ -516,6 +517,49 @@ class SyncClient:
|
|
|
516
517
|
)
|
|
517
518
|
return self._run_async(coro)
|
|
518
519
|
|
|
520
|
+
def geo_queries(
|
|
521
|
+
self,
|
|
522
|
+
queries: list[dict],
|
|
523
|
+
conc: int = 20,
|
|
524
|
+
):
|
|
525
|
+
"""
|
|
526
|
+
Execute multiple geo queries concurrently (synchronous version).
|
|
527
|
+
|
|
528
|
+
Args:
|
|
529
|
+
queries (list[dict]): List of dictionaries containing query parameters.
|
|
530
|
+
Each query must have 'expr', 'feature', and 'in_crs' keys.
|
|
531
|
+
conc (int): Number of concurrent requests to make (default 20, max 100)
|
|
532
|
+
|
|
533
|
+
Returns:
|
|
534
|
+
Union[float, geopandas.GeoDataFrame]:
|
|
535
|
+
- float: Average of all results if results are integers
|
|
536
|
+
- GeoDataFrame: GeoDataFrame with geometry and dataset columns if results are xarray datasets
|
|
537
|
+
|
|
538
|
+
Raises:
|
|
539
|
+
ValueError: If queries list is empty, concurrency is too high, or queries are malformed
|
|
540
|
+
APIError: If the API request fails
|
|
541
|
+
|
|
542
|
+
Example:
|
|
543
|
+
queries = [
|
|
544
|
+
{
|
|
545
|
+
'expr': 'WCF.wcf',
|
|
546
|
+
'feature': {'type': 'Feature', 'geometry': {...}, 'properties': {}},
|
|
547
|
+
'in_crs': 'epsg:4326'
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
'expr': 'NDVI.ndvi',
|
|
551
|
+
'feature': {'type': 'Feature', 'geometry': {...}, 'properties': {}},
|
|
552
|
+
'in_crs': 'epsg:4326'
|
|
553
|
+
}
|
|
554
|
+
]
|
|
555
|
+
result = client.geo_queries(queries)
|
|
556
|
+
"""
|
|
557
|
+
coro = self._async_client.geo_queries(
|
|
558
|
+
queries=queries,
|
|
559
|
+
conc=conc,
|
|
560
|
+
)
|
|
561
|
+
return self._run_async(coro)
|
|
562
|
+
|
|
519
563
|
async def _ensure_context(self):
|
|
520
564
|
"""Ensure the async client context is entered."""
|
|
521
565
|
if not self._context_entered and not self._closed:
|
|
@@ -529,18 +573,36 @@ class SyncClient:
|
|
|
529
573
|
self._context_entered = False
|
|
530
574
|
|
|
531
575
|
def _run_async(self, coro):
|
|
532
|
-
"""
|
|
576
|
+
"""
|
|
577
|
+
Run an async coroutine and return the result synchronously.
|
|
578
|
+
This version handles both Jupyter notebook environments and regular Python environments.
|
|
579
|
+
"""
|
|
533
580
|
async def run_with_context():
|
|
534
581
|
await self._ensure_context()
|
|
535
582
|
return await coro
|
|
536
583
|
|
|
537
584
|
try:
|
|
585
|
+
# Check if we're in a running event loop (like Jupyter)
|
|
538
586
|
loop = asyncio.get_running_loop()
|
|
539
|
-
|
|
587
|
+
|
|
588
|
+
# Method 1: Try using nest_asyncio if available
|
|
589
|
+
try:
|
|
590
|
+
import nest_asyncio
|
|
591
|
+
nest_asyncio.apply()
|
|
592
|
+
return asyncio.run(run_with_context())
|
|
593
|
+
except ImportError:
|
|
594
|
+
pass
|
|
595
|
+
|
|
596
|
+
# Method 2: Use ThreadPoolExecutor to run in a separate thread
|
|
597
|
+
def run_in_thread():
|
|
598
|
+
return asyncio.run(run_with_context())
|
|
599
|
+
|
|
540
600
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
541
|
-
future = executor.submit(
|
|
601
|
+
future = executor.submit(run_in_thread)
|
|
542
602
|
return future.result()
|
|
603
|
+
|
|
543
604
|
except RuntimeError:
|
|
605
|
+
# No running loop, safe to use asyncio.run()
|
|
544
606
|
return asyncio.run(run_with_context())
|
|
545
607
|
|
|
546
608
|
def close(self):
|
|
@@ -551,10 +613,21 @@ class SyncClient:
|
|
|
551
613
|
|
|
552
614
|
try:
|
|
553
615
|
loop = asyncio.get_running_loop()
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
616
|
+
|
|
617
|
+
# Try nest_asyncio first
|
|
618
|
+
try:
|
|
619
|
+
import nest_asyncio
|
|
620
|
+
nest_asyncio.apply()
|
|
621
|
+
asyncio.run(close_async())
|
|
622
|
+
except ImportError:
|
|
623
|
+
# Fall back to ThreadPoolExecutor
|
|
624
|
+
def run_in_thread():
|
|
625
|
+
return asyncio.run(close_async())
|
|
626
|
+
|
|
627
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
628
|
+
future = executor.submit(run_in_thread)
|
|
629
|
+
future.result()
|
|
630
|
+
|
|
558
631
|
except RuntimeError:
|
|
559
632
|
asyncio.run(close_async())
|
|
560
633
|
|
|
@@ -575,10 +648,21 @@ class SyncClient:
|
|
|
575
648
|
|
|
576
649
|
try:
|
|
577
650
|
loop = asyncio.get_running_loop()
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
651
|
+
|
|
652
|
+
# Try nest_asyncio first
|
|
653
|
+
try:
|
|
654
|
+
import nest_asyncio
|
|
655
|
+
nest_asyncio.apply()
|
|
656
|
+
asyncio.run(enter_async())
|
|
657
|
+
except ImportError:
|
|
658
|
+
# Fall back to ThreadPoolExecutor
|
|
659
|
+
def run_in_thread():
|
|
660
|
+
return asyncio.run(enter_async())
|
|
661
|
+
|
|
662
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
663
|
+
future = executor.submit(run_in_thread)
|
|
664
|
+
future.result()
|
|
665
|
+
|
|
582
666
|
except RuntimeError:
|
|
583
667
|
asyncio.run(enter_async())
|
|
584
668
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
terrakio_core/__init__.py,sha256=
|
|
1
|
+
terrakio_core/__init__.py,sha256=snOTpM6-GxHvvDJ6hjlsWywgIago1JbE8QDfsWMRlPI,273
|
|
2
2
|
terrakio_core/accessors.py,sha256=qWLljU83YO7EUOefo_f6_P6ba6uiYMXwou0ihAHKBHQ,23706
|
|
3
|
-
terrakio_core/async_client.py,sha256=
|
|
3
|
+
terrakio_core/async_client.py,sha256=M7C6by-GCW9AvDRhIwpBG12fO5--NG5qrHdSC6Fjkrc,14082
|
|
4
4
|
terrakio_core/client.py,sha256=VXP7BtJWIfpPPZR7_yNdSTcGwNgTwhb7KorusqkQrzk,5603
|
|
5
5
|
terrakio_core/config.py,sha256=r8NARVYOca4AuM88VP_j-8wQxOk1s7VcRdyEdseBlLE,4193
|
|
6
6
|
terrakio_core/exceptions.py,sha256=4qnpOM1gOxsNIXDXY4qwY1d3I4Myhp7HBh7b2D0SVrU,529
|
|
7
|
-
terrakio_core/sync_client.py,sha256=
|
|
7
|
+
terrakio_core/sync_client.py,sha256=wsVKjaIDZW4AC2-81RXseE9mFbXu90T5Bbwrgw37x6k,24864
|
|
8
8
|
terrakio_core/convenience_functions/convenience_functions.py,sha256=B7qbObjP4OuAUtrVf4Gi58c0q2EkTwOCOE568P0Q-EE,18607
|
|
9
9
|
terrakio_core/endpoints/auth.py,sha256=FdLsPScPIBo-Gxl6ZnE-46cp2molggAJtL72LssN3fg,6049
|
|
10
10
|
terrakio_core/endpoints/dataset_management.py,sha256=BUm8IIlW_Q45vDiQp16CiJGeSLheI8uWRVRQtMdhaNk,13161
|
|
@@ -16,7 +16,7 @@ terrakio_core/endpoints/user_management.py,sha256=WlFr3EfK8iI6DfkpMuYLHZUPk2n7_D
|
|
|
16
16
|
terrakio_core/helper/bounded_taskgroup.py,sha256=wiTH10jhKZgrsgrFUNG6gig8bFkUEPHkGRT2XY7Rgmo,677
|
|
17
17
|
terrakio_core/helper/decorators.py,sha256=L6om7wmWNgCei3Wy5U0aZ-70OzsCwclkjIf7SfQuhCg,2289
|
|
18
18
|
terrakio_core/helper/tiles.py,sha256=xNtp3oDD912PN_FQV5fb6uQYhwfHANuXyIcxoVCCfZU,2632
|
|
19
|
-
terrakio_core-0.4.
|
|
20
|
-
terrakio_core-0.4.
|
|
21
|
-
terrakio_core-0.4.
|
|
22
|
-
terrakio_core-0.4.
|
|
19
|
+
terrakio_core-0.4.5.dist-info/METADATA,sha256=5_6bPROpM38AJ7NJDqFzORJFG2HJR-j_X0Rg4KwriUY,1791
|
|
20
|
+
terrakio_core-0.4.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
terrakio_core-0.4.5.dist-info/top_level.txt,sha256=5cBj6O7rNWyn97ND4YuvvXm0Crv4RxttT4JZvNdOG6Q,14
|
|
22
|
+
terrakio_core-0.4.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|