altcodepro-polydb-python 2.2.2__py3-none-any.whl → 2.2.4__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.
Files changed (38) hide show
  1. altcodepro_polydb_python-2.2.4.dist-info/METADATA +489 -0
  2. altcodepro_polydb_python-2.2.4.dist-info/RECORD +57 -0
  3. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/WHEEL +1 -1
  4. polydb/__init__.py +2 -2
  5. polydb/adapters/AzureBlobStorageAdapter.py +146 -41
  6. polydb/adapters/AzureFileStorageAdapter.py +148 -43
  7. polydb/adapters/AzureQueueAdapter.py +96 -34
  8. polydb/adapters/AzureTableStorageAdapter.py +462 -119
  9. polydb/adapters/BlockchainBlobAdapter.py +111 -0
  10. polydb/adapters/BlockchainKVAdapter.py +152 -0
  11. polydb/adapters/BlockchainQueueAdapter.py +116 -0
  12. polydb/adapters/DynamoDBAdapter.py +463 -176
  13. polydb/adapters/FirestoreAdapter.py +320 -148
  14. polydb/adapters/GCPPubSubAdapter.py +217 -0
  15. polydb/adapters/GCPStorageAdapter.py +184 -39
  16. polydb/adapters/MongoDBAdapter.py +159 -39
  17. polydb/adapters/PostgreSQLAdapter.py +285 -83
  18. polydb/adapters/S3Adapter.py +172 -35
  19. polydb/adapters/S3CompatibleAdapter.py +62 -8
  20. polydb/adapters/SQSAdapter.py +121 -44
  21. polydb/adapters/VercelBlobAdapter.py +196 -0
  22. polydb/adapters/VercelKVAdapter.py +275 -283
  23. polydb/adapters/VercelQueueAdapter.py +61 -0
  24. polydb/audit/AuditStorage.py +1 -1
  25. polydb/base/NoSQLKVAdapter.py +113 -101
  26. polydb/base/ObjectStorageAdapter.py +42 -6
  27. polydb/base/QueueAdapter.py +2 -2
  28. polydb/base/SharedFilesAdapter.py +2 -2
  29. polydb/cloudDatabaseFactory.py +200 -0
  30. polydb/databaseFactory.py +434 -101
  31. polydb/models.py +63 -1
  32. polydb/query.py +111 -42
  33. altcodepro_polydb_python-2.2.2.dist-info/METADATA +0 -379
  34. altcodepro_polydb_python-2.2.2.dist-info/RECORD +0 -52
  35. polydb/adapters/PubSubAdapter.py +0 -85
  36. polydb/factory.py +0 -107
  37. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/licenses/LICENSE +0 -0
  38. {altcodepro_polydb_python-2.2.2.dist-info → altcodepro_polydb_python-2.2.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,196 @@
1
+ import os
2
+ import mimetypes
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ import requests
7
+
8
+ from ..base.ObjectStorageAdapter import ObjectStorageAdapter
9
+ from ..errors import StorageError
10
+ from ..retry import retry
11
+
12
+
13
+ class VercelBlobAdapter(ObjectStorageAdapter):
14
+ """
15
+ Vercel Blob Storage adapter.
16
+
17
+ If BLOB_READ_WRITE_TOKEN is missing, falls back to
18
+ local filesystem storage for testing.
19
+ """
20
+
21
+ def __init__(self, token: str = "", timeout: int = 10):
22
+ super().__init__()
23
+
24
+ self.token = token or os.getenv("BLOB_READ_WRITE_TOKEN")
25
+ self.timeout = timeout or int(os.getenv("VERCEL_BLOB_TIMEOUT", "10"))
26
+
27
+ # Local fallback storage for tests
28
+ self.local_dir = Path(os.getenv("VERCEL_BLOB_LOCAL_DIR", "/tmp/vercel_blob"))
29
+ self.local_dir.mkdir(parents=True, exist_ok=True)
30
+
31
+ self.local_mode = not bool(self.token)
32
+
33
+ @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
34
+ def _put_raw(
35
+ self,
36
+ key: str,
37
+ data: bytes,
38
+ fileName: str = "",
39
+ media_type: Optional[str] = None,
40
+ metadata: Dict[str, Any] | None = None,
41
+ ) -> str:
42
+ """Upload object to Vercel Blob or local fallback and return URL/path"""
43
+ try:
44
+ # --------------------------------------------------
45
+ # Resolve filename
46
+ # --------------------------------------------------
47
+ filename = fileName or os.path.basename(key)
48
+
49
+ # --------------------------------------------------
50
+ # Ensure extension from media_type
51
+ # --------------------------------------------------
52
+ if media_type:
53
+ ext = mimetypes.guess_extension(media_type) or ""
54
+ if ext and not filename.lower().endswith(ext):
55
+ filename += ext
56
+
57
+ # --------------------------------------------------
58
+ # Final blob key
59
+ # --------------------------------------------------
60
+ blob_key = f"{key.rstrip('/')}/{filename}" if fileName else key
61
+
62
+ # --------------------------------------------------
63
+ # Metadata (string-safe)
64
+ # --------------------------------------------------
65
+ safe_metadata = {str(k): str(v) for k, v in (metadata or {}).items()}
66
+ safe_metadata["filename"] = filename
67
+ if media_type:
68
+ safe_metadata["contentType"] = media_type
69
+
70
+ # --------------------------------------------------
71
+ # LOCAL MODE
72
+ # --------------------------------------------------
73
+ if self.local_mode:
74
+ path = self.local_dir / blob_key
75
+ path.parent.mkdir(parents=True, exist_ok=True)
76
+ path.write_bytes(data)
77
+
78
+ meta_path = path.with_suffix(path.suffix + ".metadata.json")
79
+ try:
80
+ import json
81
+
82
+ meta_path.write_text(json.dumps(safe_metadata, ensure_ascii=False, indent=2))
83
+ except Exception:
84
+ pass
85
+
86
+ self.logger.debug(f"Stored local Vercel blob: {blob_key}")
87
+ return str(path)
88
+
89
+ # --------------------------------------------------
90
+ # REAL VERCEL
91
+ # --------------------------------------------------
92
+ headers = {
93
+ "Authorization": f"Bearer {self.token}",
94
+ "x-content-type": media_type or "application/octet-stream",
95
+ }
96
+
97
+ for k, v in safe_metadata.items():
98
+ headers[f"x-metadata-{k}"] = v
99
+
100
+ response = requests.put(
101
+ f"https://blob.vercel-storage.com/{blob_key}",
102
+ headers=headers,
103
+ data=data,
104
+ timeout=self.timeout,
105
+ )
106
+ response.raise_for_status()
107
+
108
+ result = response.json()
109
+
110
+ self.logger.debug(f"Uploaded Vercel blob: {blob_key}, type={media_type}")
111
+
112
+ return (
113
+ result.get("url") or result.get("downloadUrl") or result.get("pathname") or blob_key
114
+ )
115
+
116
+ except Exception as e:
117
+ raise StorageError(f"Vercel Blob put failed: {e}")
118
+
119
+ @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
120
+ def get(self, key: str) -> bytes | None:
121
+ try:
122
+ if self.local_mode:
123
+ path = self.local_dir / key
124
+ if not path.exists():
125
+ return None
126
+ return path.read_bytes()
127
+
128
+ response = requests.get(
129
+ f"https://blob.vercel-storage.com/{key}",
130
+ headers={"Authorization": f"Bearer {self.token}"},
131
+ timeout=self.timeout,
132
+ )
133
+
134
+ if response.status_code == 404:
135
+ return None
136
+
137
+ response.raise_for_status()
138
+ return response.content
139
+
140
+ except StorageError:
141
+ raise
142
+ except Exception as e:
143
+ raise StorageError(f"Vercel Blob get failed: {e}")
144
+
145
+ @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
146
+ def delete(self, key: str) -> bool:
147
+ try:
148
+ if self.local_mode:
149
+ path = self.local_dir / key
150
+ if path.exists():
151
+ path.unlink()
152
+ meta_path = path.with_suffix(path.suffix + ".metadata.json")
153
+ if meta_path.exists():
154
+ meta_path.unlink()
155
+ return True
156
+
157
+ response = requests.delete(
158
+ f"https://blob.vercel-storage.com/{key}",
159
+ headers={"Authorization": f"Bearer {self.token}"},
160
+ timeout=self.timeout,
161
+ )
162
+
163
+ if response.status_code == 404:
164
+ return False
165
+
166
+ response.raise_for_status()
167
+ return True
168
+
169
+ except Exception as e:
170
+ raise StorageError(f"Vercel Blob delete failed: {e}")
171
+
172
+ @retry(max_attempts=3, delay=1.0, exceptions=(StorageError,))
173
+ def list(self, prefix: str = "") -> List[str]:
174
+ try:
175
+ if self.local_mode:
176
+ results: List[str] = []
177
+ for p in self.local_dir.rglob("*"):
178
+ if p.is_file() and not p.name.endswith(".metadata.json"):
179
+ rel = str(p.relative_to(self.local_dir))
180
+ if rel.startswith(prefix):
181
+ results.append(rel)
182
+ return results
183
+
184
+ response = requests.get(
185
+ f"https://blob.vercel-storage.com/?prefix={prefix}",
186
+ headers={"Authorization": f"Bearer {self.token}"},
187
+ timeout=self.timeout,
188
+ )
189
+
190
+ response.raise_for_status()
191
+
192
+ blobs = response.json().get("blobs", [])
193
+ return [b.get("pathname") for b in blobs if b.get("pathname")]
194
+
195
+ except Exception as e:
196
+ raise StorageError(f"Vercel Blob list failed: {e}")