hippius 0.2.2__py3-none-any.whl → 0.2.3__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.
@@ -0,0 +1,253 @@
1
+ """Rich UI components for the Hippius SDK CLI."""
2
+
3
+ import argparse
4
+ import sys
5
+ from typing import Any, Dict, List, Optional, Union
6
+
7
+ from rich.console import Console
8
+ from rich.panel import Panel
9
+ from rich.progress import (
10
+ BarColumn,
11
+ Progress,
12
+ SpinnerColumn,
13
+ TextColumn,
14
+ TimeElapsedColumn,
15
+ TimeRemainingColumn,
16
+ )
17
+ from rich.table import Table
18
+ from rich.text import Text
19
+
20
+ # Create a global console instance
21
+ console = Console()
22
+
23
+
24
+ def log(message: str, style: Optional[str] = None) -> None:
25
+ """Log a message to the console with optional styling.
26
+
27
+ Args:
28
+ message: The message to log
29
+ style: Optional style to apply to the message
30
+ """
31
+ console.print(message, style=style)
32
+
33
+
34
+ def info(message: str) -> None:
35
+ """Log an info message to the console.
36
+
37
+ Args:
38
+ message: The info message to log
39
+ """
40
+ console.print(f"[blue]INFO:[/blue] {message}")
41
+
42
+
43
+ def success(message: str) -> None:
44
+ """Log a success message to the console.
45
+
46
+ Args:
47
+ message: The success message to log
48
+ """
49
+ console.print(f"[green]SUCCESS:[/green] {message}")
50
+
51
+
52
+ def warning(message: str) -> None:
53
+ """Log a warning message to the console.
54
+
55
+ Args:
56
+ message: The warning message to log
57
+ """
58
+ console.print(f"[yellow]WARNING:[/yellow] {message}")
59
+
60
+
61
+ def error(message: str) -> None:
62
+ """Log an error message to the console.
63
+
64
+ Args:
65
+ message: The error message to log
66
+ """
67
+ console.print(f"[bold red]ERROR:[/bold red] {message}")
68
+
69
+
70
+ def print_table(
71
+ title: str,
72
+ data: List[Dict[str, Any]],
73
+ columns: List[str],
74
+ style: Optional[str] = None,
75
+ ) -> None:
76
+ """Print a table of data.
77
+
78
+ Args:
79
+ title: The title of the table
80
+ data: List of dictionaries containing the data
81
+ columns: List of column names to include
82
+ style: Optional style to apply to the table
83
+ """
84
+ # Create table with optional style and expanded width
85
+ table = Table(title=title, style=style, expand=True, show_edge=True)
86
+
87
+ # Add columns
88
+ for column in columns:
89
+ table.add_column(column)
90
+
91
+ # Add rows, applying style to each cell if provided
92
+ for row in data:
93
+ values = [str(row.get(column, "")) for column in columns]
94
+ if style:
95
+ # Apply style to each cell value if a style is provided
96
+ styled_values = [f"[{style}]{value}[/{style}]" for value in values]
97
+ table.add_row(*styled_values)
98
+ else:
99
+ table.add_row(*values)
100
+
101
+ # Print the table
102
+ console.print(table)
103
+
104
+
105
+ def print_panel(content: str, title: Optional[str] = None) -> None:
106
+ """Print content in a panel.
107
+
108
+ Args:
109
+ content: The content to display in the panel
110
+ title: Optional title for the panel
111
+ """
112
+ console.print(Panel(content, title=title))
113
+
114
+
115
+ def create_progress() -> Progress:
116
+ """Create a Rich progress bar for tracking operations.
117
+
118
+ Returns:
119
+ A Rich Progress instance configured for the Hippius CLI
120
+ """
121
+ return Progress(
122
+ SpinnerColumn(),
123
+ TextColumn("[bold blue]{task.description}"),
124
+ BarColumn(),
125
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
126
+ TimeElapsedColumn(),
127
+ TimeRemainingColumn(),
128
+ console=console,
129
+ )
130
+
131
+
132
+ def print_help_text(parser: "argparse.ArgumentParser"):
133
+ """Print help text with Rich formatting.
134
+
135
+ Args:
136
+ parser: The argparse parser to display help for
137
+ """
138
+ # Get the help text from the parser
139
+ import io
140
+
141
+ buffer = io.StringIO()
142
+ parser.print_help(buffer)
143
+ help_text = buffer.getvalue()
144
+
145
+ # Split the help text into sections
146
+ sections = help_text.split("\n\n")
147
+
148
+ # Process and print each section with appropriate styling
149
+ for i, section in enumerate(sections):
150
+ if i == 0: # Usage section
151
+ lines = section.split("\n")
152
+ title = lines[0]
153
+ usage = "\n".join(lines[1:]) if len(lines) > 1 else ""
154
+ console.print(f"[bold cyan]{title}[/bold cyan]")
155
+ if usage:
156
+ console.print(f"[yellow]{usage}[/yellow]")
157
+ elif "positional arguments:" in section:
158
+ lines = section.split("\n")
159
+ title = lines[0]
160
+ args = "\n".join(lines[1:])
161
+ console.print(f"\n[bold green]{title}[/bold green]")
162
+ console.print(args)
163
+ elif "options:" in section:
164
+ lines = section.split("\n")
165
+ title = lines[0]
166
+ opts = "\n".join(lines[1:])
167
+ console.print(f"\n[bold green]{title}[/bold green]")
168
+ console.print(opts)
169
+ elif "examples:" in section:
170
+ lines = section.split("\n")
171
+ title = lines[0]
172
+ examples = "\n".join(lines[1:])
173
+ console.print(f"\n[bold magenta]{title}[/bold magenta]")
174
+ console.print(f"[cyan]{examples}[/cyan]")
175
+ else:
176
+ console.print(f"\n{section}")
177
+
178
+
179
+ class RichHelpAction(argparse.Action):
180
+ """Custom help action that displays the Hippius logo and uses Rich formatting."""
181
+
182
+ def __init__(
183
+ self,
184
+ option_strings,
185
+ dest=argparse.SUPPRESS,
186
+ default=argparse.SUPPRESS,
187
+ help=None,
188
+ ):
189
+ super().__init__(
190
+ option_strings=option_strings,
191
+ dest=dest,
192
+ default=default,
193
+ nargs=0,
194
+ help=help,
195
+ )
196
+
197
+ def __call__(self, parser, namespace, values, option_string=None):
198
+ # Display the Hippius logo banner when help is requested
199
+ from hippius_sdk.cli_assets import HERO_TITLE
200
+
201
+ console.print(HERO_TITLE, style="bold cyan")
202
+
203
+ # Use our print_help_text function instead of the default formatter
204
+ print_help_text(parser)
205
+ parser.exit()
206
+
207
+
208
+ class ProgressTracker:
209
+ """Helper class for tracking progress in async operations with Rich progress bars."""
210
+
211
+ def __init__(self, description: str, total: int):
212
+ """Initialize a progress tracker.
213
+
214
+ Args:
215
+ description: Description for the progress bar
216
+ total: Total number of items to process
217
+ """
218
+ self.progress = create_progress()
219
+ self.task_id = None
220
+ self.description = description
221
+ self.total = total
222
+ self.completed = 0
223
+
224
+ def __enter__(self):
225
+ """Context manager entry that initializes the progress bar."""
226
+ self.progress.__enter__()
227
+ self.task_id = self.progress.add_task(self.description, total=self.total)
228
+ return self
229
+
230
+ def __exit__(self, exc_type, exc_val, exc_tb):
231
+ """Context manager exit that properly closes the progress bar."""
232
+ self.progress.__exit__(exc_type, exc_val, exc_tb)
233
+
234
+ def update(self, advance: int = 1):
235
+ """Update the progress bar.
236
+
237
+ Args:
238
+ advance: Number of steps to advance by (default: 1)
239
+ """
240
+ self.completed += advance
241
+ self.progress.update(self.task_id, completed=self.completed)
242
+
243
+ def set_description(self, description: str):
244
+ """Update the progress bar description.
245
+
246
+ Args:
247
+ description: New description text
248
+ """
249
+ self.progress.update(self.task_id, description=description)
250
+
251
+ def finish(self):
252
+ """Mark the progress as complete."""
253
+ self.progress.update(self.task_id, completed=self.total)
hippius_sdk/client.py CHANGED
@@ -3,7 +3,7 @@ Main client for the Hippius SDK.
3
3
  """
4
4
 
5
5
  import base64
6
- from typing import Any, Dict, List, Optional
6
+ from typing import Any, Callable, Dict, List, Optional
7
7
 
8
8
  import nacl.secret
9
9
  import nacl.utils
@@ -46,7 +46,9 @@ class HippiusClient:
46
46
  """
47
47
  # Load configuration values if not explicitly provided
48
48
  if ipfs_gateway is None:
49
- ipfs_gateway = get_config_value("ipfs", "gateway", "https://ipfs.io")
49
+ ipfs_gateway = get_config_value(
50
+ "ipfs", "gateway", "https://get.hippius.network"
51
+ )
50
52
 
51
53
  if ipfs_api_url is None:
52
54
  ipfs_api_url = get_config_value(
@@ -201,7 +203,7 @@ class HippiusClient:
201
203
  cid, max_display_bytes, format_output, decrypt=decrypt
202
204
  )
203
205
 
204
- def exists(self, cid: str) -> Dict[str, Any]:
206
+ async def exists(self, cid: str) -> Dict[str, Any]:
205
207
  """
206
208
  Check if a CID exists on IPFS.
207
209
 
@@ -215,9 +217,9 @@ class HippiusClient:
215
217
  - formatted_cid: Formatted version of the CID
216
218
  - gateway_url: URL to access the content if it exists
217
219
  """
218
- return self.ipfs_client.exists(cid)
220
+ return await self.ipfs_client.exists(cid)
219
221
 
220
- def pin(self, cid: str) -> Dict[str, Any]:
222
+ async def pin(self, cid: str) -> Dict[str, Any]:
221
223
  """
222
224
  Pin a CID to IPFS to keep it available.
223
225
 
@@ -231,7 +233,7 @@ class HippiusClient:
231
233
  - formatted_cid: Formatted version of the CID
232
234
  - message: Status message
233
235
  """
234
- return self.ipfs_client.pin(cid)
236
+ return await self.ipfs_client.pin(cid)
235
237
 
236
238
  def format_cid(self, cid: str) -> str:
237
239
  """
@@ -336,7 +338,7 @@ class HippiusClient:
336
338
  temp_dir: str = None,
337
339
  max_retries: int = 3,
338
340
  verbose: bool = True,
339
- ) -> str:
341
+ ) -> Dict:
340
342
  """
341
343
  Reconstruct a file from erasure-coded chunks using its metadata.
342
344
 
@@ -348,7 +350,7 @@ class HippiusClient:
348
350
  verbose: Whether to print progress information
349
351
 
350
352
  Returns:
351
- str: Path to the reconstructed file
353
+ Dict: containing file reconstruction info.
352
354
 
353
355
  Raises:
354
356
  ValueError: If reconstruction fails
@@ -372,6 +374,7 @@ class HippiusClient:
372
374
  miner_ids: List[str] = None,
373
375
  max_retries: int = 3,
374
376
  verbose: bool = True,
377
+ progress_callback: Optional[Callable[[str, int, int], None]] = None,
375
378
  ) -> Dict[str, Any]:
376
379
  """
377
380
  Erasure code a file, upload the chunks to IPFS, and store in the Hippius marketplace.
@@ -387,6 +390,8 @@ class HippiusClient:
387
390
  miner_ids: List of specific miner IDs to use for storage
388
391
  max_retries: Maximum number of retry attempts
389
392
  verbose: Whether to print progress information
393
+ progress_callback: Optional callback function for progress updates
394
+ Function receives (stage_name, current, total)
390
395
 
391
396
  Returns:
392
397
  dict: Result including metadata CID and transaction hash
@@ -405,4 +410,47 @@ class HippiusClient:
405
410
  substrate_client=self.substrate_client,
406
411
  max_retries=max_retries,
407
412
  verbose=verbose,
413
+ progress_callback=progress_callback,
414
+ )
415
+
416
+ async def delete_file(
417
+ self, cid: str, cancel_from_blockchain: bool = True
418
+ ) -> Dict[str, Any]:
419
+ """
420
+ Delete a file from IPFS and optionally cancel its storage on the blockchain.
421
+
422
+ Args:
423
+ cid: Content Identifier (CID) of the file to delete
424
+ cancel_from_blockchain: Whether to also cancel the storage request from the blockchain
425
+
426
+ Returns:
427
+ Dict containing the result of the operation
428
+
429
+ Raises:
430
+ RuntimeError: If deletion fails completely
431
+ """
432
+ return await self.ipfs_client.delete_file(cid, cancel_from_blockchain)
433
+
434
+ async def delete_ec_file(
435
+ self,
436
+ metadata_cid: str,
437
+ cancel_from_blockchain: bool = True,
438
+ parallel_limit: int = 20,
439
+ ) -> Dict[str, Any]:
440
+ """
441
+ Delete an erasure-coded file, including all its chunks in parallel.
442
+
443
+ Args:
444
+ metadata_cid: CID of the metadata file for the erasure-coded file
445
+ cancel_from_blockchain: Whether to cancel storage from blockchain
446
+ parallel_limit: Maximum number of concurrent deletion operations
447
+
448
+ Returns:
449
+ Dict containing the result of the operation
450
+
451
+ Raises:
452
+ RuntimeError: If deletion fails completely
453
+ """
454
+ return await self.ipfs_client.delete_ec_file(
455
+ metadata_cid, cancel_from_blockchain, parallel_limit
408
456
  )
hippius_sdk/config.py CHANGED
@@ -23,7 +23,7 @@ CONFIG_DIR = os.path.expanduser("~/.hippius")
23
23
  CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
24
24
  DEFAULT_CONFIG = {
25
25
  "ipfs": {
26
- "gateway": "https://ipfs.io",
26
+ "gateway": "https://get.hippius.network",
27
27
  "api_url": "https://store.hippius.network",
28
28
  "local_ipfs": False,
29
29
  },