terrakio-core 0.3.9__py3-none-any.whl → 0.4.0__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.

@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  from urllib.parse import urlparse
7
7
  from ..helper.decorators import require_token, require_api_key, require_auth
8
8
  import aiohttp
9
-
9
+ from typing import Dict, Any, Optional, List, Union
10
10
  class MassStats:
11
11
  def __init__(self, client):
12
12
  self._client = client
@@ -218,7 +218,7 @@ class MassStats:
218
218
  params["output"] = output
219
219
 
220
220
  return self._client._terrakio_request("GET", "mass_stats/download", params=params)
221
-
221
+
222
222
  @require_api_key
223
223
  async def _upload_file(self, file_path: str, url: str, use_gzip: bool = False):
224
224
  """
@@ -237,6 +237,18 @@ class MassStats:
237
237
  except json.JSONDecodeError as e:
238
238
  raise ValueError(f"Invalid JSON in file {file_path}: {e}")
239
239
 
240
+ return await self._upload_json_data(json_data, url, use_gzip)
241
+
242
+ @require_api_key
243
+ async def _upload_json_data(self, json_data: Union[Dict, List], url: str, use_gzip: bool = False):
244
+ """
245
+ Helper method to upload JSON data directly to a signed URL.
246
+
247
+ Args:
248
+ json_data: JSON data (dict or list) to upload
249
+ url: Signed URL to upload to
250
+ use_gzip: Whether to compress the data with gzip
251
+ """
240
252
  if hasattr(json, 'dumps') and 'ignore_nan' in json.dumps.__code__.co_varnames:
241
253
  dumps_kwargs = {'ignore_nan': True}
242
254
  else:
@@ -253,6 +265,7 @@ class MassStats:
253
265
  headers = {
254
266
  'Content-Type': 'application/json'
255
267
  }
268
+
256
269
  response = await self._client._regular_request("PUT", url, data=body, headers=headers)
257
270
  return response
258
271
 
@@ -386,36 +399,55 @@ class MassStats:
386
399
  region: str,
387
400
  output: str,
388
401
  config: Dict[str, Any],
389
- request_json: Dict[str, Any],
390
- manifest_json: Dict[str, Any],
402
+ request_json: str, # Path to request JSON file
391
403
  overwrite: bool = False,
392
404
  skip_existing: bool = False,
393
405
  location: str = None,
394
406
  force_loc: bool = None,
395
- server: str = "dev-au.terrak.io"
407
+ server: str = None
396
408
  ) -> Dict[str, Any]:
397
409
  """
398
410
  Execute a mass stats job.
399
-
411
+
400
412
  Args:
401
413
  name: The name of the job
402
414
  region: The region of the job
403
415
  output: The output of the job
404
416
  config: The config of the job
405
- request_json: The request JSON
406
- manifest_json: The manifest JSON
417
+ request_json: Path to the request JSON file
407
418
  overwrite: Whether to overwrite the job
408
419
  skip_existing: Whether to skip existing jobs
409
420
  location: The location of the job
410
421
  force_loc: Whether to force the location
411
422
  server: The server to use
412
-
423
+
413
424
  Returns:
414
425
  API response as a dictionary
415
-
426
+
416
427
  Raises:
417
428
  APIError: If the API request fails
418
429
  """
430
+
431
+ def extract_manifest_from_request(request_data: List[Dict[str, Any]]) -> List[str]:
432
+ """Extract unique group names from request data to create manifest list."""
433
+ groups = []
434
+ seen_groups = set()
435
+
436
+ for item in request_data:
437
+ if not isinstance(item, dict):
438
+ raise ValueError("Each item in request JSON should be a dictionary")
439
+
440
+ if 'group' not in item:
441
+ raise ValueError("Each item should have a 'group' field")
442
+
443
+ group = item['group']
444
+ if group not in seen_groups:
445
+ groups.append(group)
446
+ seen_groups.add(group)
447
+
448
+ return groups
449
+
450
+ # Load and validate request JSON
419
451
  try:
420
452
  with open(request_json, 'r') as file:
421
453
  request_data = json.load(file)
@@ -427,14 +459,35 @@ class MassStats:
427
459
  return e
428
460
  except json.JSONDecodeError as e:
429
461
  return e
430
- upload_result = await self._upload_request(name = name, size = size, region = region, output = output, config = config, location = location, force_loc = force_loc, overwrite = overwrite, server = server, skip_existing = skip_existing)
462
+
463
+ # Generate manifest from request data (kept in memory)
464
+ try:
465
+ manifest_groups = extract_manifest_from_request(request_data)
466
+ except Exception as e:
467
+ raise ValueError(f"Error extracting manifest from request JSON: {e}")
468
+
469
+ # Get upload URLs
470
+ upload_result = await self._upload_request(
471
+ name=name,
472
+ size=size,
473
+ region=region,
474
+ output=output,
475
+ config=config,
476
+ location=location,
477
+ force_loc=force_loc,
478
+ overwrite=overwrite,
479
+ server=server,
480
+ skip_existing=skip_existing
481
+ )
482
+
431
483
  requests_url = upload_result.get('requests_url')
432
484
  manifest_url = upload_result.get('manifest_url')
485
+
433
486
  if not requests_url:
434
487
  raise ValueError("No requests_url returned from server for request JSON upload")
435
488
 
489
+ # Upload request JSON file
436
490
  try:
437
- # in this place we are uploading the request json file, we need to check whether the json is in the correct format or not
438
491
  self.validate_request(request_json)
439
492
  requests_response = await self._upload_file(request_json, requests_url, use_gzip=True)
440
493
  if requests_response.status not in [200, 201, 204]:
@@ -446,15 +499,17 @@ class MassStats:
446
499
  if not manifest_url:
447
500
  raise ValueError("No manifest_url returned from server for manifest JSON upload")
448
501
 
502
+ # Upload manifest JSON data directly (no temporary file needed)
449
503
  try:
450
- manifest_response = await self._upload_file(manifest_json, manifest_url, use_gzip=False)
504
+ manifest_response = await self._upload_json_data(manifest_groups, manifest_url, use_gzip=False)
451
505
  if manifest_response.status not in [200, 201, 204]:
452
506
  self._client.logger.error(f"Manifest upload error: {manifest_response.text()}")
453
507
  raise Exception(f"Failed to upload manifest JSON: {manifest_response.text()}")
454
508
  except Exception as e:
455
- raise Exception(f"Error uploading manifest JSON file {manifest_json}: {e}")
456
-
457
- start_job_task_id =await self.start_job(upload_result.get("id"))
509
+ raise Exception(f"Error uploading manifest JSON: {e}")
510
+
511
+ # Start the job
512
+ start_job_task_id = await self.start_job(upload_result.get("id"))
458
513
  return start_job_task_id
459
514
 
460
515
  @require_api_key