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 CHANGED
@@ -5,7 +5,7 @@ Terrakio Core
5
5
  Core components for Terrakio API clients.
6
6
  """
7
7
 
8
- __version__ = "0.4.4"
8
+ __version__ = "0.4.5"
9
9
 
10
10
  from .async_client import AsyncClient
11
11
  from .sync_client import SyncClient as Client
@@ -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 = {
@@ -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
- """Run an async coroutine and return the result synchronously."""
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
- import concurrent.futures
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(asyncio.run, run_with_context())
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
- import concurrent.futures
555
- with concurrent.futures.ThreadPoolExecutor() as executor:
556
- future = executor.submit(asyncio.run, close_async())
557
- future.result()
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
- import concurrent.futures
579
- with concurrent.futures.ThreadPoolExecutor() as executor:
580
- future = executor.submit(asyncio.run, enter_async())
581
- future.result()
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: terrakio-core
3
- Version: 0.4.4
3
+ Version: 0.4.5
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
@@ -1,10 +1,10 @@
1
- terrakio_core/__init__.py,sha256=tHjogyeQC-EKWpfPNnQqieQWGYRagVnj_LBiPP8vZrw,273
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=FYUuN1IboFkygylo0jFjEmhBGoHhzhAwG_KznkQR2y4,12449
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=HkLavfbT1sXGE1kTkiCDgNJxL9bErgOD6WihFrM-2xI,21873
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.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,,
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,,