pinarkive-sdk 2.0.0__tar.gz → 2.1.45__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.
- pinarkive_sdk-2.1.45/PKG-INFO +455 -0
- pinarkive_sdk-2.1.45/README.md +443 -0
- pinarkive_sdk-2.1.45/pinarkive_client.py +287 -0
- pinarkive_sdk-2.1.45/pinarkive_sdk.egg-info/PKG-INFO +455 -0
- {pinarkive_sdk-2.0.0 → pinarkive_sdk-2.1.45}/pyproject.toml +2 -2
- pinarkive_sdk-2.0.0/PKG-INFO +0 -44
- pinarkive_sdk-2.0.0/README.md +0 -32
- pinarkive_sdk-2.0.0/pinarkive_client.py +0 -140
- pinarkive_sdk-2.0.0/pinarkive_sdk.egg-info/PKG-INFO +0 -44
- {pinarkive_sdk-2.0.0 → pinarkive_sdk-2.1.45}/pinarkive_sdk.egg-info/SOURCES.txt +0 -0
- {pinarkive_sdk-2.0.0 → pinarkive_sdk-2.1.45}/pinarkive_sdk.egg-info/dependency_links.txt +0 -0
- {pinarkive_sdk-2.0.0 → pinarkive_sdk-2.1.45}/pinarkive_sdk.egg-info/requires.txt +0 -0
- {pinarkive_sdk-2.0.0 → pinarkive_sdk-2.1.45}/pinarkive_sdk.egg-info/top_level.txt +0 -0
- {pinarkive_sdk-2.0.0 → pinarkive_sdk-2.1.45}/setup.cfg +0 -0
@@ -0,0 +1,455 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pinarkive-sdk
|
3
|
+
Version: 2.1.45
|
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
|
+
|
51
|
+
### JWT Token Authentication
|
52
|
+
```python
|
53
|
+
client = PinarkiveClient(token="your-jwt-token-here")
|
54
|
+
```
|
55
|
+
|
56
|
+
## Basic Usage
|
57
|
+
|
58
|
+
### File Upload
|
59
|
+
```python
|
60
|
+
# Upload single file
|
61
|
+
result = client.upload_file("document.pdf")
|
62
|
+
response_data = result.json()
|
63
|
+
print(f"CID: {response_data['cid']}")
|
64
|
+
print(f"Status: {response_data['status']}")
|
65
|
+
```
|
66
|
+
|
67
|
+
### Directory Upload
|
68
|
+
```python
|
69
|
+
# Upload directory from local path
|
70
|
+
result = client.upload_directory("/path/to/directory")
|
71
|
+
print(f"Directory CID: {result.json()['cid']}")
|
72
|
+
```
|
73
|
+
|
74
|
+
### List Uploads
|
75
|
+
```python
|
76
|
+
# List all uploaded files with pagination
|
77
|
+
result = client.list_uploads(page=1, limit=20)
|
78
|
+
response_data = result.json()
|
79
|
+
print(f"Uploads: {response_data['uploads']}")
|
80
|
+
print(f"Total: {response_data['pagination']['total']}")
|
81
|
+
```
|
82
|
+
|
83
|
+
## Advanced Features
|
84
|
+
|
85
|
+
### Directory DAG Upload
|
86
|
+
Upload entire directory structures as DAG (Directed Acyclic Graph):
|
87
|
+
|
88
|
+
```python
|
89
|
+
# Create project structure
|
90
|
+
project_files = {
|
91
|
+
"src/index.py": "print('Hello World')",
|
92
|
+
"src/utils.py": "def utils(): pass",
|
93
|
+
"requirements.txt": "requests>=2.31.0",
|
94
|
+
"README.md": "# My Project\n\nThis is my project."
|
95
|
+
}
|
96
|
+
|
97
|
+
# Upload as DAG
|
98
|
+
result = client.upload_directory_dag(project_files, dir_name="my-project")
|
99
|
+
response_data = result.json()
|
100
|
+
print(f"DAG CID: {response_data['dagCid']}")
|
101
|
+
print(f"Files: {response_data['files']}")
|
102
|
+
```
|
103
|
+
|
104
|
+
### Directory Cluster Upload
|
105
|
+
```python
|
106
|
+
# Upload using cluster-based approach
|
107
|
+
files = [
|
108
|
+
{"path": "file1.txt", "content": "Content 1"},
|
109
|
+
{"path": "file2.txt", "content": "Content 2"}
|
110
|
+
]
|
111
|
+
|
112
|
+
result = client.upload_directory_cluster(files)
|
113
|
+
print(f"Cluster CID: {result.json()['cid']}")
|
114
|
+
```
|
115
|
+
|
116
|
+
### Upload File to Existing Directory
|
117
|
+
```python
|
118
|
+
# Add file to existing directory
|
119
|
+
result = client.upload_file_to_directory("new-file.txt", "existing-directory-path")
|
120
|
+
print(f"File added to directory: {result.json()['cid']}")
|
121
|
+
```
|
122
|
+
|
123
|
+
### File Renaming
|
124
|
+
```python
|
125
|
+
# Rename an uploaded file
|
126
|
+
result = client.rename_file("upload-id-here", "new-file-name.pdf")
|
127
|
+
print(f"File renamed: {result.json()['updated']}")
|
128
|
+
```
|
129
|
+
|
130
|
+
### Pinning Operations
|
131
|
+
|
132
|
+
#### Basic CID Pinning
|
133
|
+
```python
|
134
|
+
result = client.pin_cid("QmYourCIDHere")
|
135
|
+
print(f"CID pinned: {result.json()['pinned']}")
|
136
|
+
```
|
137
|
+
|
138
|
+
#### Pin with Custom Name
|
139
|
+
```python
|
140
|
+
result = client.pin_cid_with_name("QmYourCIDHere", "my-important-file")
|
141
|
+
print(f"CID pinned with name: {result.json()['pinned']}")
|
142
|
+
```
|
143
|
+
|
144
|
+
### API Key Management
|
145
|
+
|
146
|
+
#### Generate API Key
|
147
|
+
```python
|
148
|
+
# Basic token generation
|
149
|
+
token = client.generate_token("my-app")
|
150
|
+
|
151
|
+
# Advanced token with options
|
152
|
+
token = client.generate_token("my-app", {
|
153
|
+
"expires_in_days": 30,
|
154
|
+
"ip_allowlist": ["192.168.1.1", "10.0.0.1"],
|
155
|
+
"permissions": ["upload", "pin"]
|
156
|
+
})
|
157
|
+
print(f"New API key: {token.json()['token']}")
|
158
|
+
```
|
159
|
+
|
160
|
+
#### List API Keys
|
161
|
+
```python
|
162
|
+
tokens = client.list_tokens()
|
163
|
+
print(f"API Keys: {tokens.json()['tokens']}")
|
164
|
+
```
|
165
|
+
|
166
|
+
#### Revoke API Key
|
167
|
+
```python
|
168
|
+
result = client.revoke_token("my-app")
|
169
|
+
print(f"Token revoked: {result.json()['revoked']}")
|
170
|
+
```
|
171
|
+
|
172
|
+
## Type Hints Support
|
173
|
+
|
174
|
+
The SDK includes comprehensive type hints for better IDE support:
|
175
|
+
|
176
|
+
```python
|
177
|
+
from typing import Dict, Any, Optional
|
178
|
+
from pinarkive_client import PinarkiveClient
|
179
|
+
|
180
|
+
# Type hints provide better autocomplete and error checking
|
181
|
+
client = PinarkiveClient(api_key="your-key")
|
182
|
+
|
183
|
+
# IDE will show parameter types and return types
|
184
|
+
def upload_project_files(files: Dict[str, str]) -> Any:
|
185
|
+
return client.upload_directory_dag(files, dir_name="project")
|
186
|
+
|
187
|
+
# Type hints for options
|
188
|
+
token_options: Dict[str, Any] = {
|
189
|
+
"expires_in_days": 30,
|
190
|
+
"ip_allowlist": ["192.168.1.1"]
|
191
|
+
}
|
192
|
+
token = client.generate_token("my-app", token_options)
|
193
|
+
```
|
194
|
+
|
195
|
+
## Error Handling
|
196
|
+
|
197
|
+
```python
|
198
|
+
import requests
|
199
|
+
|
200
|
+
try:
|
201
|
+
result = client.upload_file("document.pdf")
|
202
|
+
print("Success:", result.json())
|
203
|
+
except requests.exceptions.RequestException as e:
|
204
|
+
if hasattr(e, 'response') and e.response is not None:
|
205
|
+
print(f"API Error: {e.response.status_code}")
|
206
|
+
print(f"Response: {e.response.json()}")
|
207
|
+
else:
|
208
|
+
print(f"Network Error: {e}")
|
209
|
+
```
|
210
|
+
|
211
|
+
## Integration Examples
|
212
|
+
|
213
|
+
### Django Integration
|
214
|
+
```python
|
215
|
+
# views.py
|
216
|
+
from django.http import JsonResponse
|
217
|
+
from django.views.decorators.csrf import csrf_exempt
|
218
|
+
from pinarkive_client import PinarkiveClient
|
219
|
+
import json
|
220
|
+
|
221
|
+
@csrf_exempt
|
222
|
+
def upload_file(request):
|
223
|
+
if request.method == 'POST':
|
224
|
+
client = PinarkiveClient(api_key=settings.PINARKIVE_API_KEY)
|
225
|
+
|
226
|
+
uploaded_file = request.FILES['file']
|
227
|
+
# Save temporarily
|
228
|
+
with open(f'/tmp/{uploaded_file.name}', 'wb+') as destination:
|
229
|
+
for chunk in uploaded_file.chunks():
|
230
|
+
destination.write(chunk)
|
231
|
+
|
232
|
+
try:
|
233
|
+
result = client.upload_file(f'/tmp/{uploaded_file.name}')
|
234
|
+
return JsonResponse(result.json())
|
235
|
+
except Exception as e:
|
236
|
+
return JsonResponse({'error': str(e)}, status=500)
|
237
|
+
|
238
|
+
return JsonResponse({'error': 'Method not allowed'}, status=405)
|
239
|
+
```
|
240
|
+
|
241
|
+
### Flask Integration
|
242
|
+
```python
|
243
|
+
from flask import Flask, request, jsonify
|
244
|
+
from pinarkive_client import PinarkiveClient
|
245
|
+
import os
|
246
|
+
|
247
|
+
app = Flask(__name__)
|
248
|
+
client = PinarkiveClient(api_key=os.environ.get('PINARKIVE_API_KEY'))
|
249
|
+
|
250
|
+
@app.route('/upload', methods=['POST'])
|
251
|
+
def upload_file():
|
252
|
+
if 'file' not in request.files:
|
253
|
+
return jsonify({'error': 'No file provided'}), 400
|
254
|
+
|
255
|
+
file = request.files['file']
|
256
|
+
if file.filename == '':
|
257
|
+
return jsonify({'error': 'No file selected'}), 400
|
258
|
+
|
259
|
+
# Save temporarily
|
260
|
+
temp_path = f'/tmp/{file.filename}'
|
261
|
+
file.save(temp_path)
|
262
|
+
|
263
|
+
try:
|
264
|
+
result = client.upload_file(temp_path)
|
265
|
+
os.remove(temp_path) # Clean up
|
266
|
+
return jsonify(result.json())
|
267
|
+
except Exception as e:
|
268
|
+
os.remove(temp_path) # Clean up on error
|
269
|
+
return jsonify({'error': str(e)}), 500
|
270
|
+
|
271
|
+
@app.route('/files', methods=['GET'])
|
272
|
+
def list_files():
|
273
|
+
try:
|
274
|
+
result = client.list_uploads()
|
275
|
+
return jsonify(result.json())
|
276
|
+
except Exception as e:
|
277
|
+
return jsonify({'error': str(e)}), 500
|
278
|
+
```
|
279
|
+
|
280
|
+
### FastAPI Integration
|
281
|
+
```python
|
282
|
+
from fastapi import FastAPI, File, UploadFile, HTTPException
|
283
|
+
from pinarkive_client import PinarkiveClient
|
284
|
+
import tempfile
|
285
|
+
import os
|
286
|
+
|
287
|
+
app = FastAPI()
|
288
|
+
client = PinarkiveClient(api_key=os.environ.get('PINARKIVE_API_KEY'))
|
289
|
+
|
290
|
+
@app.post("/upload")
|
291
|
+
async def upload_file(file: UploadFile = File(...)):
|
292
|
+
# Create temporary file
|
293
|
+
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
294
|
+
content = await file.read()
|
295
|
+
temp_file.write(content)
|
296
|
+
temp_file.flush()
|
297
|
+
|
298
|
+
try:
|
299
|
+
result = client.upload_file(temp_file.name)
|
300
|
+
os.unlink(temp_file.name) # Clean up
|
301
|
+
return result.json()
|
302
|
+
except Exception as e:
|
303
|
+
os.unlink(temp_file.name) # Clean up on error
|
304
|
+
raise HTTPException(status_code=500, detail=str(e))
|
305
|
+
|
306
|
+
@app.get("/files")
|
307
|
+
async def list_files(page: int = 1, limit: int = 10):
|
308
|
+
try:
|
309
|
+
result = client.list_uploads(page=page, limit=limit)
|
310
|
+
return result.json()
|
311
|
+
except Exception as e:
|
312
|
+
raise HTTPException(status_code=500, detail=str(e))
|
313
|
+
```
|
314
|
+
|
315
|
+
## API Reference
|
316
|
+
|
317
|
+
### Constructor
|
318
|
+
```python
|
319
|
+
PinarkiveClient(token: Optional[str] = None, api_key: Optional[str] = None, base_url: str = 'https://api.pinarkive.com/api/v2')
|
320
|
+
```
|
321
|
+
- `token`: Optional JWT token for authentication
|
322
|
+
- `api_key`: Optional API key for authentication
|
323
|
+
- `base_url`: Base URL for the API (defaults to production)
|
324
|
+
|
325
|
+
### File Operations
|
326
|
+
- `upload_file(file_path: str)` - Upload single file
|
327
|
+
- `upload_directory(dir_path: str)` - Upload directory from path
|
328
|
+
- `upload_directory_dag(files_dict: Dict[str, Any], dir_name: Optional[str] = None)` - Upload directory as DAG
|
329
|
+
- `upload_directory_cluster(files: List[Dict[str, Any]])` - Upload directory using cluster
|
330
|
+
- `upload_file_to_directory(file_path: str, dir_path: str)` - Add file to existing directory
|
331
|
+
- `rename_file(upload_id: str, new_name: str)` - Rename uploaded file
|
332
|
+
- `remove_file(cid: str)` - Remove file from storage
|
333
|
+
|
334
|
+
### Pinning Operations
|
335
|
+
- `pin_cid(cid: str)` - Pin CID to account
|
336
|
+
- `pin_cid_with_name(cid: str, custom_name: Optional[str] = None)` - Pin CID with custom name
|
337
|
+
|
338
|
+
### User Operations
|
339
|
+
- `get_profile()` - Get user profile
|
340
|
+
- `update_profile(data: Dict[str, Any])` - Update user profile
|
341
|
+
- `list_uploads(page: int = 1, limit: int = 10)` - List uploaded files
|
342
|
+
- `delete_upload(cid: str)` - Delete uploaded file
|
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)
|