discovery-engine-api 0.2.78__tar.gz → 0.2.80__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: discovery-engine-api
3
- Version: 0.2.78
3
+ Version: 0.2.80
4
4
  Summary: Python SDK for the Discovery Engine API
5
5
  Project-URL: Homepage, https://www.leap-labs.com
6
6
  Project-URL: Documentation, https://disco.leap-labs.com/llms-full.txt
@@ -1,6 +1,6 @@
1
1
  """Discovery Engine Python SDK."""
2
2
 
3
- __version__ = "0.2.78"
3
+ __version__ = "0.2.80"
4
4
 
5
5
  from discovery.client import Engine
6
6
  from discovery.types import (
@@ -395,7 +395,7 @@ class Engine:
395
395
  num_columns: Number of columns in the dataset.
396
396
  num_rows: Number of rows (improves time estimate accuracy).
397
397
  depth_iterations: Depth iterations (1=fast, higher=deeper).
398
- visibility: "public" (free, depth=1) or "private" (costs credits).
398
+ visibility: "public" (free, results published) or "private" (costs credits).
399
399
 
400
400
  Returns:
401
401
  Dict with ``cost``, ``time_estimate``, ``limits``, and ``account`` info.
@@ -445,6 +445,15 @@ class Engine:
445
445
  status=data["status"],
446
446
  job_id=data.get("job_id"),
447
447
  job_status=data.get("job_status"),
448
+ queue_position=data.get("queue_position"),
449
+ current_step=data.get("current_step", {}).get("status")
450
+ if data.get("current_step")
451
+ else None,
452
+ current_step_message=data.get("current_step", {}).get("message")
453
+ if data.get("current_step")
454
+ else None,
455
+ estimated_seconds=data.get("estimated_seconds"),
456
+ estimated_wait_seconds=data.get("estimated_wait_seconds"),
448
457
  error_message=data.get("error_message"),
449
458
  )
450
459
 
@@ -463,6 +472,7 @@ class Engine:
463
472
  """
464
473
  start_time = time.time()
465
474
  last_status = None
475
+ last_step = None
466
476
  poll_count = 0
467
477
  consecutive_errors = 0
468
478
  max_consecutive_errors = 3
@@ -500,18 +510,53 @@ class Engine:
500
510
  elapsed = time.time() - start_time
501
511
  poll_count += 1
502
512
 
503
- if result.status != last_status or poll_count % 3 == 0:
504
- status_msg = f"Status: {result.status}"
505
- if result.job_status:
506
- status_msg += f" (job: {result.job_status})"
507
- if elapsed > 0:
508
- status_msg += f" | Elapsed: {elapsed:.1f}s"
513
+ if result.status != "completed" and (
514
+ result.status != last_status
515
+ or result.current_step != last_step
516
+ or poll_count % 3 == 0
517
+ ):
518
+ if result.job_status == "pending":
519
+ pos = result.queue_position
520
+ pos_str = f" (position {pos} in queue)" if pos is not None else ""
521
+ wait_str = ""
522
+ if result.estimated_wait_seconds is not None:
523
+ mins = max(1, round(result.estimated_wait_seconds / 60))
524
+ wait_str = f" | Est. wait: ~{mins} min"
525
+ status_msg = f"Status: waiting{pos_str}{wait_str} | Upgrade at disco.leap-labs.com/account for priority processing"
526
+ else:
527
+ step_str = ""
528
+ if result.current_step and result.current_step not in (
529
+ "pending",
530
+ "completed",
531
+ "failed",
532
+ ):
533
+ msg = (
534
+ f" — {result.current_step_message}"
535
+ if result.current_step_message
536
+ else ""
537
+ )
538
+ step_str = f" ({result.current_step}{msg})"
539
+ eta_str = ""
540
+ if result.estimated_seconds is not None and elapsed > 0:
541
+ remaining = max(0, result.estimated_seconds - elapsed)
542
+ if remaining > 0:
543
+ eta_str = f" | ETA: ~{max(1, round(remaining / 60))} min"
544
+ status_msg = (
545
+ f"Status: {result.status}{step_str} | Elapsed: {elapsed:.1f}s{eta_str}"
546
+ )
509
547
  self._log(f" {status_msg}")
510
548
 
511
549
  last_status = result.status
550
+ last_step = result.current_step
512
551
 
513
552
  if result.status == "completed":
514
- self._log(f"Run completed in {elapsed:.1f}s")
553
+ n = len(result.patterns)
554
+ pattern_str = f"{n} pattern{'s' if n != 1 else ''} found"
555
+ self._log(f"Run completed in {elapsed:.1f}s | {pattern_str}")
556
+ for hint in result.hints:
557
+ self._log(hint)
558
+ if result.report_url:
559
+ self._log(f"Report: {result.report_url}")
515
560
  return result
516
561
  elif result.status == "failed":
517
562
  error_msg = result.error_message or "Unknown error"
@@ -731,11 +776,11 @@ class Engine:
731
776
  Returns:
732
777
  EngineResult with run_id and (if wait=True) complete results.
733
778
  """
734
- # Warn if depth > 1 with public visibility (server will cap to 1)
779
+ # Public runs are always depth=1 (server enforces this)
735
780
  if depth_iterations > 1 and visibility == "public":
736
781
  self._log(
737
- "Public runs are limited to depth 1. "
738
- "Set visibility='private' for deeper analysis (requires credits)."
782
+ "Public runs use depth=1. Upgrade your plan at disco.leap-labs.com/subscribe "
783
+ "to see more patterns and get priority processing."
739
784
  )
740
785
  depth_iterations = 1
741
786
 
@@ -751,9 +796,7 @@ class Engine:
751
796
  title=title,
752
797
  log=True,
753
798
  )
754
- self._log(
755
- f"Uploading file and creating run (depth: {depth_iterations}, target: {target_column})..."
756
- )
799
+ self._log("Uploading file and creating run...")
757
800
 
758
801
  # Step 1: Upload file
759
802
  self._log(" Uploading to storage...")
@@ -1004,9 +1047,6 @@ class Engine:
1004
1047
  hidden_deep_count = data.get("hidden_deep_count", 0)
1005
1048
  hidden_deep_novel_count = data.get("hidden_deep_novel_count", 0)
1006
1049
 
1007
- for hint in hints:
1008
- self._log(hint)
1009
-
1010
1050
  return EngineResult(
1011
1051
  run_id=data["run_id"],
1012
1052
  report_id=data.get("report_id"),
@@ -1023,6 +1063,15 @@ class Engine:
1023
1063
  feature_importance=feature_importance,
1024
1064
  job_id=data.get("job_id"),
1025
1065
  job_status=data.get("job_status"),
1066
+ queue_position=data.get("queue_position"),
1067
+ current_step=data.get("current_step", {}).get("status")
1068
+ if data.get("current_step")
1069
+ else None,
1070
+ current_step_message=data.get("current_step", {}).get("message")
1071
+ if data.get("current_step")
1072
+ else None,
1073
+ estimated_seconds=data.get("estimated_seconds"),
1074
+ estimated_wait_seconds=data.get("estimated_wait_seconds"),
1026
1075
  error_message=data.get("error_message"),
1027
1076
  report_url=report_url,
1028
1077
  hints=hints,
@@ -39,7 +39,7 @@ class InsufficientCreditsError(DiscoveryError):
39
39
  super().__init__(
40
40
  message,
41
41
  suggestion=(
42
- "Run with visibility='public' (free, depth=1) or purchase credits "
42
+ "Run with visibility='public' (free, results published) or purchase credits "
43
43
  "with engine.purchase_credits()."
44
44
  ),
45
45
  )
@@ -202,6 +202,11 @@ class EngineResult:
202
202
  # Job tracking
203
203
  job_id: Optional[str] = None
204
204
  job_status: Optional[str] = None
205
+ queue_position: Optional[int] = None
206
+ current_step: Optional[str] = None
207
+ current_step_message: Optional[str] = None
208
+ estimated_seconds: Optional[int] = None
209
+ estimated_wait_seconds: Optional[int] = None
205
210
  error_message: Optional[str] = None
206
211
 
207
212
  # Shareable link to the interactive web report
@@ -221,4 +226,9 @@ class RunStatus:
221
226
  status: str
222
227
  job_id: Optional[str] = None
223
228
  job_status: Optional[str] = None
229
+ queue_position: Optional[int] = None
230
+ current_step: Optional[str] = None
231
+ current_step_message: Optional[str] = None
232
+ estimated_seconds: Optional[int] = None
233
+ estimated_wait_seconds: Optional[int] = None
224
234
  error_message: Optional[str] = None
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "discovery-engine-api"
3
- version = "0.2.78"
3
+ version = "0.2.80"
4
4
  description = "Python SDK for the Discovery Engine API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"