pinarkive-sdk 2.0.0__tar.gz → 2.1.46__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.
@@ -0,0 +1,455 @@
1
+ Metadata-Version: 2.4
2
+ Name: pinarkive-sdk
3
+ Version: 2.1.46
4
+ Summary: Python SDK for the Pinarkive API v2.1 - Easy IPFS file management with directory DAG uploads, file renaming, and enhanced API key management. Includes type hints for better IDE support.
5
+ Author: ITCS VIP, Joel_da
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/pinarkive/pinarkive-sdk
8
+ Project-URL: Repository, https://github.com/pinarkive/pinarkive-sdk.git
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: requests>=2.31.0
12
+
13
+ # Pinarkive Python SDK
14
+
15
+ Python client for the Pinarkive API v2.1. Easy IPFS file management with directory DAG uploads, file renaming, and enhanced API key management. Includes type hints for better IDE support and Pythonic usage patterns.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install pinarkive-sdk
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```python
26
+ from pinarkive_client import PinarkiveClient
27
+
28
+ # Initialize with API key
29
+ client = PinarkiveClient(api_key="your-api-key-here")
30
+
31
+ # Upload a file
32
+ result = client.upload_file("document.pdf")
33
+ print(f"File uploaded: {result.json()['cid']}")
34
+
35
+ # Generate API key
36
+ token = client.generate_token("my-app", {
37
+ "expires_in_days": 30
38
+ })
39
+ print(f"New API key: {token.json()['token']}")
40
+ ```
41
+
42
+ ## Authentication
43
+
44
+ The SDK supports two authentication methods:
45
+
46
+ ### API Key Authentication (Recommended)
47
+ ```python
48
+ client = PinarkiveClient(api_key="your-api-key-here")
49
+ ```
50
+ **Note:** The SDK automatically sends the API key using the `Authorization: Bearer` header format, not `X-API-Key`.
51
+
52
+ ### JWT Token Authentication
53
+ ```python
54
+ client = PinarkiveClient(token="your-jwt-token-here")
55
+ ```
56
+
57
+ ## Basic Usage
58
+
59
+ ### File Upload
60
+ ```python
61
+ # Upload single file
62
+ result = client.upload_file("document.pdf")
63
+ response_data = result.json()
64
+ print(f"CID: {response_data['cid']}")
65
+ print(f"Status: {response_data['status']}")
66
+ ```
67
+
68
+ ### Directory Upload
69
+ ```python
70
+ # Upload directory from local path
71
+ result = client.upload_directory("/path/to/directory")
72
+ print(f"Directory CID: {result.json()['cid']}")
73
+ ```
74
+
75
+ ### List Uploads
76
+ ```python
77
+ # List all uploaded files with pagination
78
+ result = client.list_uploads(page=1, limit=20)
79
+ response_data = result.json()
80
+ print(f"Uploads: {response_data['uploads']}")
81
+ print(f"Total: {response_data['pagination']['total']}")
82
+ ```
83
+
84
+ ## Advanced Features
85
+
86
+ ### Directory DAG Upload
87
+ Upload entire directory structures as DAG (Directed Acyclic Graph):
88
+
89
+ ```python
90
+ # Create project structure
91
+ project_files = {
92
+ "src/index.py": "print('Hello World')",
93
+ "src/utils.py": "def utils(): pass",
94
+ "requirements.txt": "requests>=2.31.0",
95
+ "README.md": "# My Project\n\nThis is my project."
96
+ }
97
+
98
+ # Upload as DAG
99
+ result = client.upload_directory_dag(project_files, dir_name="my-project")
100
+ response_data = result.json()
101
+ print(f"DAG CID: {response_data['dagCid']}")
102
+ print(f"Files: {response_data['files']}")
103
+ ```
104
+
105
+ ### Directory Cluster Upload
106
+ ```python
107
+ # Upload using cluster-based approach
108
+ files = [
109
+ {"path": "file1.txt", "content": "Content 1"},
110
+ {"path": "file2.txt", "content": "Content 2"}
111
+ ]
112
+
113
+ result = client.upload_directory_cluster(files)
114
+ print(f"Cluster CID: {result.json()['cid']}")
115
+ ```
116
+
117
+ ### Upload File to Existing Directory
118
+ ```python
119
+ # Add file to existing directory
120
+ result = client.upload_file_to_directory("new-file.txt", "existing-directory-path")
121
+ print(f"File added to directory: {result.json()['cid']}")
122
+ ```
123
+
124
+ ### File Renaming
125
+ ```python
126
+ # Rename an uploaded file
127
+ result = client.rename_file("upload-id-here", "new-file-name.pdf")
128
+ print(f"File renamed: {result.json()['updated']}")
129
+ ```
130
+
131
+ ### Pinning Operations
132
+
133
+ #### Basic CID Pinning
134
+ ```python
135
+ result = client.pin_cid("QmYourCIDHere")
136
+ print(f"CID pinned: {result.json()['pinned']}")
137
+ ```
138
+
139
+ #### Pin with Custom Name
140
+ ```python
141
+ result = client.pin_cid_with_name("QmYourCIDHere", "my-important-file")
142
+ print(f"CID pinned with name: {result.json()['pinned']}")
143
+ ```
144
+
145
+ ### API Key Management
146
+
147
+ #### Generate API Key
148
+ ```python
149
+ # Basic token generation
150
+ token = client.generate_token("my-app")
151
+
152
+ # Advanced token with options
153
+ token = client.generate_token("my-app", {
154
+ "expires_in_days": 30,
155
+ "ip_allowlist": ["192.168.1.1", "10.0.0.1"],
156
+ "permissions": ["upload", "pin"]
157
+ })
158
+ print(f"New API key: {token.json()['token']}")
159
+ ```
160
+
161
+ #### List API Keys
162
+ ```python
163
+ tokens = client.list_tokens()
164
+ print(f"API Keys: {tokens.json()['tokens']}")
165
+ ```
166
+
167
+ #### Revoke API Key
168
+ ```python
169
+ result = client.revoke_token("my-app")
170
+ print(f"Token revoked: {result.json()['revoked']}")
171
+ ```
172
+
173
+ ## Type Hints Support
174
+
175
+ The SDK includes comprehensive type hints for better IDE support:
176
+
177
+ ```python
178
+ from typing import Dict, Any, Optional
179
+ from pinarkive_client import PinarkiveClient
180
+
181
+ # Type hints provide better autocomplete and error checking
182
+ client = PinarkiveClient(api_key="your-key")
183
+
184
+ # IDE will show parameter types and return types
185
+ def upload_project_files(files: Dict[str, str]) -> Any:
186
+ return client.upload_directory_dag(files, dir_name="project")
187
+
188
+ # Type hints for options
189
+ token_options: Dict[str, Any] = {
190
+ "expires_in_days": 30,
191
+ "ip_allowlist": ["192.168.1.1"]
192
+ }
193
+ token = client.generate_token("my-app", token_options)
194
+ ```
195
+
196
+ ## Error Handling
197
+
198
+ ```python
199
+ import requests
200
+
201
+ try:
202
+ result = client.upload_file("document.pdf")
203
+ print("Success:", result.json())
204
+ except requests.exceptions.RequestException as e:
205
+ if hasattr(e, 'response') and e.response is not None:
206
+ print(f"API Error: {e.response.status_code}")
207
+ print(f"Response: {e.response.json()}")
208
+ else:
209
+ print(f"Network Error: {e}")
210
+ ```
211
+
212
+ ## Integration Examples
213
+
214
+ ### Django Integration
215
+ ```python
216
+ # views.py
217
+ from django.http import JsonResponse
218
+ from django.views.decorators.csrf import csrf_exempt
219
+ from pinarkive_client import PinarkiveClient
220
+ import json
221
+
222
+ @csrf_exempt
223
+ def upload_file(request):
224
+ if request.method == 'POST':
225
+ client = PinarkiveClient(api_key=settings.PINARKIVE_API_KEY)
226
+
227
+ uploaded_file = request.FILES['file']
228
+ # Save temporarily
229
+ with open(f'/tmp/{uploaded_file.name}', 'wb+') as destination:
230
+ for chunk in uploaded_file.chunks():
231
+ destination.write(chunk)
232
+
233
+ try:
234
+ result = client.upload_file(f'/tmp/{uploaded_file.name}')
235
+ return JsonResponse(result.json())
236
+ except Exception as e:
237
+ return JsonResponse({'error': str(e)}, status=500)
238
+
239
+ return JsonResponse({'error': 'Method not allowed'}, status=405)
240
+ ```
241
+
242
+ ### Flask Integration
243
+ ```python
244
+ from flask import Flask, request, jsonify
245
+ from pinarkive_client import PinarkiveClient
246
+ import os
247
+
248
+ app = Flask(__name__)
249
+ client = PinarkiveClient(api_key=os.environ.get('PINARKIVE_API_KEY'))
250
+
251
+ @app.route('/upload', methods=['POST'])
252
+ def upload_file():
253
+ if 'file' not in request.files:
254
+ return jsonify({'error': 'No file provided'}), 400
255
+
256
+ file = request.files['file']
257
+ if file.filename == '':
258
+ return jsonify({'error': 'No file selected'}), 400
259
+
260
+ # Save temporarily
261
+ temp_path = f'/tmp/{file.filename}'
262
+ file.save(temp_path)
263
+
264
+ try:
265
+ result = client.upload_file(temp_path)
266
+ os.remove(temp_path) # Clean up
267
+ return jsonify(result.json())
268
+ except Exception as e:
269
+ os.remove(temp_path) # Clean up on error
270
+ return jsonify({'error': str(e)}), 500
271
+
272
+ @app.route('/files', methods=['GET'])
273
+ def list_files():
274
+ try:
275
+ result = client.list_uploads()
276
+ return jsonify(result.json())
277
+ except Exception as e:
278
+ return jsonify({'error': str(e)}), 500
279
+ ```
280
+
281
+ ### FastAPI Integration
282
+ ```python
283
+ from fastapi import FastAPI, File, UploadFile, HTTPException
284
+ from pinarkive_client import PinarkiveClient
285
+ import tempfile
286
+ import os
287
+
288
+ app = FastAPI()
289
+ client = PinarkiveClient(api_key=os.environ.get('PINARKIVE_API_KEY'))
290
+
291
+ @app.post("/upload")
292
+ async def upload_file(file: UploadFile = File(...)):
293
+ # Create temporary file
294
+ with tempfile.NamedTemporaryFile(delete=False) as temp_file:
295
+ content = await file.read()
296
+ temp_file.write(content)
297
+ temp_file.flush()
298
+
299
+ try:
300
+ result = client.upload_file(temp_file.name)
301
+ os.unlink(temp_file.name) # Clean up
302
+ return result.json()
303
+ except Exception as e:
304
+ os.unlink(temp_file.name) # Clean up on error
305
+ raise HTTPException(status_code=500, detail=str(e))
306
+
307
+ @app.get("/files")
308
+ async def list_files(page: int = 1, limit: int = 10):
309
+ try:
310
+ result = client.list_uploads(page=page, limit=limit)
311
+ return result.json()
312
+ except Exception as e:
313
+ raise HTTPException(status_code=500, detail=str(e))
314
+ ```
315
+
316
+ ## API Reference
317
+
318
+ ### Constructor
319
+ ```python
320
+ PinarkiveClient(token: Optional[str] = None, api_key: Optional[str] = None, base_url: str = 'https://api.pinarkive.com/api/v2')
321
+ ```
322
+ - `token`: Optional JWT token for authentication
323
+ - `api_key`: Optional API key for authentication
324
+ - `base_url`: Base URL for the API (defaults to production)
325
+
326
+ ### File Operations
327
+ - `upload_file(file_path: str)` - Upload single file
328
+ - `upload_directory(dir_path: str)` - Upload directory from path
329
+ - `upload_directory_dag(files_dict: Dict[str, Any], dir_name: Optional[str] = None)` - Upload directory as DAG
330
+ - `upload_directory_cluster(files: List[Dict[str, Any]])` - Upload directory using cluster
331
+ - `upload_file_to_directory(file_path: str, dir_path: str)` - Add file to existing directory
332
+ - `rename_file(upload_id: str, new_name: str)` - Rename uploaded file
333
+ - `remove_file(cid: str)` - Remove file from storage
334
+
335
+ ### Pinning Operations
336
+ - `pin_cid(cid: str)` - Pin CID to account
337
+ - `pin_cid_with_name(cid: str, custom_name: Optional[str] = None)` - Pin CID with custom name
338
+
339
+ ### User Operations
340
+ - `get_profile()` - Get user profile
341
+ - `update_profile(data: Dict[str, Any])` - Update user profile
342
+ - `list_uploads(page: int = 1, limit: int = 10)` - List uploaded files
343
+ - `get_referrals()` - Get referral information
344
+
345
+ ### Token Management
346
+ - `generate_token(name: str, options: Optional[Dict[str, Any]] = None)` - Generate API key
347
+ - `list_tokens()` - List all API keys
348
+ - `revoke_token(name: str)` - Revoke API key
349
+
350
+ ### Authentication
351
+ - `login(email: str, password: str)` - Login with credentials
352
+ - `signup(data: Dict[str, Any], locale: Optional[str] = None, refCode: Optional[str] = None)` - Create new account
353
+ - `logout()` - Logout current session
354
+
355
+ ### Status & Monitoring
356
+ - `get_status(cid: str)` - Get file status
357
+ - `get_allocations(cid: str)` - Get storage allocations
358
+
359
+ ## Examples
360
+
361
+ ### Complete File Management Workflow
362
+ ```python
363
+ from pinarkive_client import PinarkiveClient
364
+
365
+ def manage_files():
366
+ client = PinarkiveClient(api_key="your-api-key")
367
+
368
+ try:
369
+ # 1. Upload a file
370
+ result = client.upload_file("document.pdf")
371
+ upload_data = result.json()
372
+ print(f"Uploaded: {upload_data['cid']}")
373
+
374
+ # 2. Pin the CID with a custom name
375
+ pin_result = client.pin_cid_with_name(upload_data['cid'], "important-document")
376
+ print(f"Pinned: {pin_result.json()['pinned']}")
377
+
378
+ # 3. Rename the file
379
+ if 'uploadId' in upload_data:
380
+ rename_result = client.rename_file(upload_data['uploadId'], "my-document.pdf")
381
+ print(f"Renamed: {rename_result.json()['updated']}")
382
+
383
+ # 4. List all uploads
384
+ uploads = client.list_uploads()
385
+ print(f"All uploads: {uploads.json()['uploads']}")
386
+
387
+ except Exception as e:
388
+ print(f"Error: {e}")
389
+
390
+ manage_files()
391
+ ```
392
+
393
+ ### Directory Upload Workflow
394
+ ```python
395
+ def upload_project():
396
+ client = PinarkiveClient(api_key="your-api-key")
397
+
398
+ # Create project structure
399
+ project_files = {
400
+ "src/main.py": "print('Hello World')",
401
+ "src/utils.py": "def helper(): pass",
402
+ "requirements.txt": "requests>=2.31.0",
403
+ "README.md": "# My Project\n\nThis is my project."
404
+ }
405
+
406
+ try:
407
+ result = client.upload_directory_dag(project_files, dir_name="my-project")
408
+ response_data = result.json()
409
+ print(f"Project uploaded: {response_data['dagCid']}")
410
+ print(f"Files: {response_data['files']}")
411
+ except Exception as e:
412
+ print(f"Upload failed: {e}")
413
+
414
+ upload_project()
415
+ ```
416
+
417
+ ### Batch File Processing
418
+ ```python
419
+ import os
420
+ from pathlib import Path
421
+
422
+ def upload_directory_contents(directory_path: str):
423
+ client = PinarkiveClient(api_key="your-api-key")
424
+
425
+ files_dict = {}
426
+ directory = Path(directory_path)
427
+
428
+ # Recursively collect all files
429
+ for file_path in directory.rglob('*'):
430
+ if file_path.is_file():
431
+ # Get relative path from directory
432
+ relative_path = str(file_path.relative_to(directory))
433
+
434
+ # Read file content
435
+ with open(file_path, 'r', encoding='utf-8') as f:
436
+ content = f.read()
437
+
438
+ files_dict[relative_path] = content
439
+
440
+ try:
441
+ result = client.upload_directory_dag(files_dict, dir_name=directory.name)
442
+ print(f"Directory uploaded: {result.json()['dagCid']}")
443
+ except Exception as e:
444
+ print(f"Upload failed: {e}")
445
+
446
+ # Usage
447
+ upload_directory_contents("./my-project")
448
+ ```
449
+
450
+ ## Support
451
+
452
+ For issues or questions:
453
+ - GitHub Issues: [https://github.com/pinarkive/pinarkive-sdk/issues](https://github.com/pinarkive/pinarkive-sdk/issues)
454
+ - API Documentation: [https://api.pinarkive.com/docs](https://api.pinarkive.com/docs)
455
+ - Contact: [https://pinarkive.com/docs.php](https://pinarkive.com/docs.php)