memwal 0.2.2.dev3__py3-none-any.whl → 0.2.2.dev4__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.
- memwal/__init__.py +5 -1
- memwal/client.py +130 -11
- memwal/compatibility.py +6 -0
- memwal/mock.py +11 -0
- memwal/types.py +8 -0
- {memwal-0.2.2.dev3.dist-info → memwal-0.2.2.dev4.dist-info}/METADATA +3 -2
- memwal-0.2.2.dev4.dist-info/RECORD +10 -0
- memwal-0.2.2.dev3.dist-info/RECORD +0 -10
- {memwal-0.2.2.dev3.dist-info → memwal-0.2.2.dev4.dist-info}/WHEEL +0 -0
memwal/__init__.py
CHANGED
|
@@ -27,6 +27,7 @@ from .client import (
|
|
|
27
27
|
MemWalClockDriftError,
|
|
28
28
|
MemWalCompatibilityError,
|
|
29
29
|
MemWalError,
|
|
30
|
+
MemWalJsonBodyError,
|
|
30
31
|
MemWalRateLimited,
|
|
31
32
|
MemWalRememberJobFailed,
|
|
32
33
|
MemWalRememberJobNotFound,
|
|
@@ -43,6 +44,7 @@ from .types import (
|
|
|
43
44
|
AskMemory,
|
|
44
45
|
AskResult,
|
|
45
46
|
EmbedResult,
|
|
47
|
+
ForgetResult,
|
|
46
48
|
HealthResult,
|
|
47
49
|
MemWalConfig,
|
|
48
50
|
NamespacesResult,
|
|
@@ -83,6 +85,7 @@ __all__ = [
|
|
|
83
85
|
"MemWalError",
|
|
84
86
|
"MemWalCompatibilityError",
|
|
85
87
|
"MemWalClockDriftError",
|
|
88
|
+
"MemWalJsonBodyError",
|
|
86
89
|
"MemWalRateLimited",
|
|
87
90
|
"MemWalRememberJobFailed",
|
|
88
91
|
"MemWalRememberJobNotFound",
|
|
@@ -118,6 +121,7 @@ __all__ = [
|
|
|
118
121
|
"AnalyzedFact",
|
|
119
122
|
"HealthResult",
|
|
120
123
|
"RestoreResult",
|
|
124
|
+
"ForgetResult",
|
|
121
125
|
"NamespaceSummary",
|
|
122
126
|
"NamespacesResult",
|
|
123
127
|
"ScoringWeights",
|
|
@@ -128,4 +132,4 @@ __all__ = [
|
|
|
128
132
|
"RecallManualResult",
|
|
129
133
|
]
|
|
130
134
|
|
|
131
|
-
__version__ = "0.2.2.
|
|
135
|
+
__version__ = "0.2.2.dev4"
|
memwal/client.py
CHANGED
|
@@ -51,6 +51,7 @@ from .types import (
|
|
|
51
51
|
AskMemory,
|
|
52
52
|
AskResult,
|
|
53
53
|
EmbedResult,
|
|
54
|
+
ForgetResult,
|
|
54
55
|
HealthResult,
|
|
55
56
|
MemWalConfig,
|
|
56
57
|
NamespacesResult,
|
|
@@ -675,7 +676,7 @@ class MemWal:
|
|
|
675
676
|
if generated_key:
|
|
676
677
|
self._pending_remember_keys.pop(request_identity, None)
|
|
677
678
|
return RememberAcceptedResult(
|
|
678
|
-
job_id=data
|
|
679
|
+
job_id=_require(data, "job_id", "POST /api/remember"),
|
|
679
680
|
status=data.get("status", "pending"),
|
|
680
681
|
)
|
|
681
682
|
|
|
@@ -717,6 +718,10 @@ class MemWal:
|
|
|
717
718
|
# Status is metadata. No SEAL decrypt, so no session. Matches TS.
|
|
718
719
|
include_seal_session=False,
|
|
719
720
|
)
|
|
721
|
+
except MemWalJsonBodyError as err:
|
|
722
|
+
if err.status != 404:
|
|
723
|
+
raise
|
|
724
|
+
data = None
|
|
720
725
|
except (json.JSONDecodeError, UnicodeDecodeError):
|
|
721
726
|
data = None
|
|
722
727
|
if not isinstance(data, dict):
|
|
@@ -800,6 +805,10 @@ class MemWal:
|
|
|
800
805
|
)
|
|
801
806
|
else:
|
|
802
807
|
raise
|
|
808
|
+
except MemWalJsonBodyError as err:
|
|
809
|
+
if err.status == 404:
|
|
810
|
+
raise MemWalRememberJobNotFound(job_id) from None
|
|
811
|
+
raise
|
|
803
812
|
except (json.JSONDecodeError, UnicodeDecodeError):
|
|
804
813
|
raise MemWalRememberJobNotFound(job_id) from None
|
|
805
814
|
except _HttpStatusError as err:
|
|
@@ -1244,6 +1253,30 @@ class MemWal:
|
|
|
1244
1253
|
dropped_count=dropped,
|
|
1245
1254
|
)
|
|
1246
1255
|
|
|
1256
|
+
async def forget(self, namespace: Optional[str] = None) -> ForgetResult:
|
|
1257
|
+
"""Delete this owner's index rows for ``namespace``.
|
|
1258
|
+
|
|
1259
|
+
Wraps ``POST /api/forget``. Walrus blobs persist; the rows stop being
|
|
1260
|
+
retrievable. Defaults to the client namespace.
|
|
1261
|
+
"""
|
|
1262
|
+
resolved_namespace = self._resolve_namespace(namespace)
|
|
1263
|
+
data = await self._signed_request(
|
|
1264
|
+
"POST",
|
|
1265
|
+
"/api/forget",
|
|
1266
|
+
{"namespace": resolved_namespace},
|
|
1267
|
+
include_seal_session=False,
|
|
1268
|
+
)
|
|
1269
|
+
endpoint = "POST /api/forget"
|
|
1270
|
+
return ForgetResult(
|
|
1271
|
+
deleted=int(_require(data, "deleted", endpoint)),
|
|
1272
|
+
namespace=_require(data, "namespace", endpoint),
|
|
1273
|
+
owner=_require(data, "owner", endpoint),
|
|
1274
|
+
)
|
|
1275
|
+
|
|
1276
|
+
async def forget_namespace(self, namespace: Optional[str] = None) -> ForgetResult:
|
|
1277
|
+
"""Alias for :meth:`forget` matching :meth:`MemWalMock.forget_namespace`."""
|
|
1278
|
+
return await self.forget(namespace)
|
|
1279
|
+
|
|
1247
1280
|
async def analyze(
|
|
1248
1281
|
self,
|
|
1249
1282
|
text: str,
|
|
@@ -1562,7 +1595,7 @@ class MemWal:
|
|
|
1562
1595
|
raise _destroyed_client_error()
|
|
1563
1596
|
if response.status_code != 200:
|
|
1564
1597
|
raise MemWalError(f"Health check failed: {response.status_code}")
|
|
1565
|
-
data = response
|
|
1598
|
+
data = _parse_json_response(response, "GET /health")
|
|
1566
1599
|
return HealthResult(
|
|
1567
1600
|
status=_require(data, "status", "GET /health"),
|
|
1568
1601
|
version=_require(data, "version", "GET /health"),
|
|
@@ -1690,7 +1723,7 @@ class MemWal:
|
|
|
1690
1723
|
if self._destroyed:
|
|
1691
1724
|
raise _destroyed_client_error()
|
|
1692
1725
|
if version_response.status_code == 200:
|
|
1693
|
-
metadata = version_response
|
|
1726
|
+
metadata = _parse_json_response(version_response, "GET /version")
|
|
1694
1727
|
elif version_response.status_code in (404, 405):
|
|
1695
1728
|
health_response = await self._http.get(f"{self._server_url}/health")
|
|
1696
1729
|
if self._destroyed:
|
|
@@ -1701,7 +1734,7 @@ class MemWal:
|
|
|
1701
1734
|
f"GET /version returned {version_response.status_code}, "
|
|
1702
1735
|
f"and GET /health returned {health_response.status_code}"
|
|
1703
1736
|
)
|
|
1704
|
-
metadata = health_response
|
|
1737
|
+
metadata = _parse_json_response(health_response, "GET /health")
|
|
1705
1738
|
else:
|
|
1706
1739
|
raise MemWalError(
|
|
1707
1740
|
"Walrus Memory compatibility check failed: "
|
|
@@ -1723,7 +1756,11 @@ class MemWal:
|
|
|
1723
1756
|
if response.status_code != 200:
|
|
1724
1757
|
raise MemWalError(f"GET /config returned {response.status_code}")
|
|
1725
1758
|
|
|
1726
|
-
data = response
|
|
1759
|
+
data = _parse_json_response(response, "GET /config")
|
|
1760
|
+
if not isinstance(data, dict):
|
|
1761
|
+
raise MemWalError(
|
|
1762
|
+
f"GET /config response was {type(data).__name__}, expected an object"
|
|
1763
|
+
)
|
|
1727
1764
|
package_id = data.get("packageId")
|
|
1728
1765
|
network = data.get("network")
|
|
1729
1766
|
sui_rpc_url = data.get("suiRpcUrl")
|
|
@@ -1758,8 +1795,9 @@ class MemWal:
|
|
|
1758
1795
|
)
|
|
1759
1796
|
if response.status_code != 200:
|
|
1760
1797
|
raise MemWalError(f"Sui GraphQL returned {response.status_code}")
|
|
1761
|
-
body = response
|
|
1762
|
-
|
|
1798
|
+
body = _parse_json_response(response, f"POST {graphql_url}")
|
|
1799
|
+
data = body.get("data") if isinstance(body, dict) else None
|
|
1800
|
+
obj = data.get("object") if isinstance(data, dict) else None
|
|
1763
1801
|
if not isinstance(obj, dict) or obj.get("version") is None:
|
|
1764
1802
|
raise MemWalError(f"Sui GraphQL could not resolve package {package_id}")
|
|
1765
1803
|
return obj["version"]
|
|
@@ -1780,8 +1818,8 @@ class MemWal:
|
|
|
1780
1818
|
if response.status_code != 200:
|
|
1781
1819
|
raise MemWalError(f"sui_getObject returned {response.status_code}")
|
|
1782
1820
|
|
|
1783
|
-
body = response
|
|
1784
|
-
result = body.get("result", {})
|
|
1821
|
+
body = _parse_json_response(response, f"POST {sui_rpc_url}")
|
|
1822
|
+
result = body.get("result", {}) if isinstance(body, dict) else {}
|
|
1785
1823
|
version = None
|
|
1786
1824
|
if isinstance(result, dict):
|
|
1787
1825
|
data = result.get("data")
|
|
@@ -1904,7 +1942,7 @@ class MemWal:
|
|
|
1904
1942
|
)
|
|
1905
1943
|
if self._destroyed:
|
|
1906
1944
|
raise _destroyed_client_error()
|
|
1907
|
-
owner = data.get("owner")
|
|
1945
|
+
owner = data.get("owner") if isinstance(data, dict) else None
|
|
1908
1946
|
if not owner:
|
|
1909
1947
|
raise MemWalError(
|
|
1910
1948
|
"Walrus Memory could not resolve this account's owner address "
|
|
@@ -2052,7 +2090,15 @@ class MemWal:
|
|
|
2052
2090
|
retry_after=response.headers.get("retry-after"),
|
|
2053
2091
|
)
|
|
2054
2092
|
|
|
2055
|
-
|
|
2093
|
+
endpoint = f"{method_upper} {path}"
|
|
2094
|
+
data = _parse_json_response(response, endpoint)
|
|
2095
|
+
if response.status_code != 404 and not isinstance(data, dict):
|
|
2096
|
+
raise MemWalJsonBodyError(
|
|
2097
|
+
status=response.status_code,
|
|
2098
|
+
endpoint=endpoint,
|
|
2099
|
+
body=response.text,
|
|
2100
|
+
)
|
|
2101
|
+
return data
|
|
2056
2102
|
|
|
2057
2103
|
|
|
2058
2104
|
class MemWalError(Exception):
|
|
@@ -2076,6 +2122,71 @@ class MemWalClockDriftError(MemWalError):
|
|
|
2076
2122
|
pass
|
|
2077
2123
|
|
|
2078
2124
|
|
|
2125
|
+
class MemWalJsonBodyError(MemWalError):
|
|
2126
|
+
"""Raised when an HTTP response that should carry JSON has an empty or non-JSON body."""
|
|
2127
|
+
|
|
2128
|
+
def __init__(
|
|
2129
|
+
self,
|
|
2130
|
+
status: int,
|
|
2131
|
+
endpoint: str,
|
|
2132
|
+
body: str,
|
|
2133
|
+
*,
|
|
2134
|
+
empty: bool = False,
|
|
2135
|
+
) -> None:
|
|
2136
|
+
redacted = _redact_internal_urls(body.strip()[:200]) if body else ""
|
|
2137
|
+
if empty:
|
|
2138
|
+
message = (
|
|
2139
|
+
f"MemWal ({endpoint}): HTTP {status} response had an empty body; "
|
|
2140
|
+
"expected JSON"
|
|
2141
|
+
)
|
|
2142
|
+
elif redacted:
|
|
2143
|
+
message = (
|
|
2144
|
+
f"MemWal ({endpoint}): HTTP {status} response was not JSON: "
|
|
2145
|
+
f"{redacted}"
|
|
2146
|
+
)
|
|
2147
|
+
else:
|
|
2148
|
+
message = f"MemWal ({endpoint}): HTTP {status} response was not JSON"
|
|
2149
|
+
super().__init__(message)
|
|
2150
|
+
self.status = status
|
|
2151
|
+
self.endpoint = endpoint
|
|
2152
|
+
self.body = body
|
|
2153
|
+
|
|
2154
|
+
|
|
2155
|
+
def _parse_json_response(response: httpx.Response, endpoint: str) -> Any:
|
|
2156
|
+
"""Decode a JSON response body or raise :class:`MemWalJsonBodyError` (#1219).
|
|
2157
|
+
|
|
2158
|
+
Mirrors the TypeScript SDK's ``jsonBodyError`` guard (#1201 / #1207): an
|
|
2159
|
+
empty or non-JSON 2xx response from a relayer or proxy in front of one
|
|
2160
|
+
surfaces as a :class:`MemWalError` naming the endpoint and HTTP status
|
|
2161
|
+
rather than Python's raw :class:`json.JSONDecodeError` or
|
|
2162
|
+
:class:`UnicodeDecodeError`.
|
|
2163
|
+
"""
|
|
2164
|
+
try:
|
|
2165
|
+
return response.json()
|
|
2166
|
+
except UnicodeDecodeError as exc:
|
|
2167
|
+
raise MemWalJsonBodyError(
|
|
2168
|
+
status=response.status_code,
|
|
2169
|
+
endpoint=endpoint,
|
|
2170
|
+
body="",
|
|
2171
|
+
) from exc
|
|
2172
|
+
except (json.JSONDecodeError, ValueError) as exc:
|
|
2173
|
+
doc = getattr(exc, "doc", None)
|
|
2174
|
+
if isinstance(doc, str):
|
|
2175
|
+
raw = doc
|
|
2176
|
+
else:
|
|
2177
|
+
try:
|
|
2178
|
+
raw = response.text
|
|
2179
|
+
except UnicodeDecodeError:
|
|
2180
|
+
raw = ""
|
|
2181
|
+
is_empty = not raw or not raw.strip()
|
|
2182
|
+
raise MemWalJsonBodyError(
|
|
2183
|
+
status=response.status_code,
|
|
2184
|
+
endpoint=endpoint,
|
|
2185
|
+
body=raw,
|
|
2186
|
+
empty=is_empty,
|
|
2187
|
+
) from exc
|
|
2188
|
+
|
|
2189
|
+
|
|
2079
2190
|
def _redact_internal_urls(text: str) -> str:
|
|
2080
2191
|
return re.sub(
|
|
2081
2192
|
r"https?://(?:(?:[\w-]+\.)*localhost|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[::1\]|0\.0\.0\.0)(?::\d+)?[^\s)\]>'\"]*",
|
|
@@ -2396,6 +2507,14 @@ class MemWalSync:
|
|
|
2396
2507
|
:class:`RecallParams` for the recommended object-style call)."""
|
|
2397
2508
|
return self._run(self._inner.recall(query, limit, namespace, max_distance))
|
|
2398
2509
|
|
|
2510
|
+
def forget(self, namespace: Optional[str] = None) -> ForgetResult:
|
|
2511
|
+
"""Synchronous version of :meth:`MemWal.forget`."""
|
|
2512
|
+
return self._run(self._inner.forget(namespace))
|
|
2513
|
+
|
|
2514
|
+
def forget_namespace(self, namespace: Optional[str] = None) -> ForgetResult:
|
|
2515
|
+
"""Synchronous version of :meth:`MemWal.forget_namespace`."""
|
|
2516
|
+
return self._run(self._inner.forget_namespace(namespace))
|
|
2517
|
+
|
|
2399
2518
|
def analyze(
|
|
2400
2519
|
self,
|
|
2401
2520
|
text: str,
|
memwal/compatibility.py
CHANGED
|
@@ -12,6 +12,12 @@ SUPPORTED_RELAYER_API_MAJOR = 1
|
|
|
12
12
|
def compatibility_error(metadata: Dict[str, Any], server_url: str) -> Optional[str]:
|
|
13
13
|
"""Return an actionable error string when relayer metadata is unsupported."""
|
|
14
14
|
|
|
15
|
+
if not isinstance(metadata, dict):
|
|
16
|
+
return (
|
|
17
|
+
f"Walrus Memory relayer at {server_url} does not expose compatibility metadata. "
|
|
18
|
+
"Upgrade the relayer to a version that serves GET /version, or use an older SDK."
|
|
19
|
+
)
|
|
20
|
+
|
|
15
21
|
api_version = metadata.get("apiVersion")
|
|
16
22
|
relayer_version = metadata.get("relayerVersion")
|
|
17
23
|
min_supported = metadata.get("minSupportedSdk")
|
memwal/mock.py
CHANGED
|
@@ -20,6 +20,7 @@ from .types import (
|
|
|
20
20
|
AskMemory,
|
|
21
21
|
AskResult,
|
|
22
22
|
EmbedResult,
|
|
23
|
+
ForgetResult,
|
|
23
24
|
HealthResult,
|
|
24
25
|
NamespacesResult,
|
|
25
26
|
NamespaceSummary,
|
|
@@ -497,6 +498,13 @@ class MemWalMock:
|
|
|
497
498
|
return True
|
|
498
499
|
return False
|
|
499
500
|
|
|
501
|
+
async def forget_namespace(self, namespace: Optional[str] = None) -> ForgetResult:
|
|
502
|
+
resolved = self._namespace if namespace is None else namespace
|
|
503
|
+
if not resolved:
|
|
504
|
+
raise ValueError("namespace cannot be empty")
|
|
505
|
+
deleted = self.clear(resolved)
|
|
506
|
+
return ForgetResult(deleted=deleted, namespace=resolved, owner=self._owner)
|
|
507
|
+
|
|
500
508
|
def clear(self, namespace: Optional[str] = None) -> int:
|
|
501
509
|
removed = [
|
|
502
510
|
memory
|
|
@@ -717,6 +725,9 @@ class MemWalMockSync:
|
|
|
717
725
|
def forget(self, blob_id: str) -> bool:
|
|
718
726
|
return self._inner.forget(blob_id)
|
|
719
727
|
|
|
728
|
+
def forget_namespace(self, namespace: Optional[str] = None) -> ForgetResult:
|
|
729
|
+
return self._run(self._inner.forget_namespace(namespace))
|
|
730
|
+
|
|
720
731
|
def clear(self, namespace: Optional[str] = None) -> int:
|
|
721
732
|
return self._inner.clear(namespace)
|
|
722
733
|
|
memwal/types.py
CHANGED
|
@@ -84,6 +84,14 @@ class RememberResult:
|
|
|
84
84
|
namespace: str
|
|
85
85
|
|
|
86
86
|
|
|
87
|
+
@dataclass
|
|
88
|
+
class ForgetResult:
|
|
89
|
+
"""Result from POST /api/forget. Walrus blobs are not deleted."""
|
|
90
|
+
|
|
91
|
+
deleted: int
|
|
92
|
+
namespace: str
|
|
93
|
+
owner: str
|
|
94
|
+
|
|
87
95
|
@dataclass
|
|
88
96
|
class RecallMemory:
|
|
89
97
|
"""A single recalled memory."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: memwal
|
|
3
|
-
Version: 0.2.2.
|
|
3
|
+
Version: 0.2.2.dev4
|
|
4
4
|
Summary: Python SDK for Walrus Memory — Privacy-first AI memory with Ed25519 signing
|
|
5
5
|
Project-URL: Homepage, https://memory.walrus.xyz
|
|
6
6
|
Project-URL: Documentation, https://memory.walrus.xyz
|
|
@@ -147,7 +147,7 @@ async def test_memory_flow():
|
|
|
147
147
|
assert "dark mode" in result.results[0].text
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
The mock supports remember/job polling, bulk remember, recall, analyze, embed, ask, health, restore, list_namespaces, `forget(blob_id)
|
|
150
|
+
The mock supports remember/job polling, bulk remember, recall, analyze, embed, ask, health, restore, list_namespaces, `forget(blob_id)` (synchronous per-blob deletion returning `bool`), `forget_namespace(namespace?)` (namespace erasure returning `ForgetResult`), and `clear(namespace?)`. For deterministic behavior, `analyze` stores its full input as one fact instead of invoking an LLM extractor. Its simple relevance score is for application tests, not production search-quality evaluation.
|
|
151
151
|
|
|
152
152
|
### Context Manager
|
|
153
153
|
|
|
@@ -254,6 +254,7 @@ Create a new async client.
|
|
|
254
254
|
| `await analyze(text, namespace?)` | Extract and store facts |
|
|
255
255
|
| `await ask(question, limit?, namespace?)` | Ask a question answered using memories |
|
|
256
256
|
| `await restore(namespace, limit?)` | Restore a namespace |
|
|
257
|
+
| `await forget(namespace?)` | Delete index rows for the namespace. Walrus blobs stay. Returns `ForgetResult`. |
|
|
257
258
|
| `await list_namespaces(cursor?, limit?)` | List namespaces that hold memories; paginate on `has_more` |
|
|
258
259
|
| `await health()` | Check server health |
|
|
259
260
|
| `await remember_manual(opts)` | Store encrypted payload + pre-computed vector |
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
memwal/__init__.py,sha256=1sCBW-L4ec1F4AX7BCOPRzaPyRmthtaeA0zGjKrdaMs,3232
|
|
2
|
+
memwal/client.py,sha256=eCp7wnvWryITN_Z3fw_NwBV1u1_mlU_mVrdBhLUoltM,102076
|
|
3
|
+
memwal/compatibility.py,sha256=R3Gt1gVRjYSLNa78leNrTpGMZI1UATYo7N8Ie_44CGI,3054
|
|
4
|
+
memwal/middleware.py,sha256=z2xdbvaobBg4byJXnrX7amWdVYE4jfeO4t31DoDBv_o,38413
|
|
5
|
+
memwal/mock.py,sha256=oG0znsO-gekoCkQ0mNgT1kjQwP1ku8TjQEkaNkbRDlQ,24878
|
|
6
|
+
memwal/types.py,sha256=jekUFnpGhVezU_VavY4DEzty6EWb0GxAwspmszk5Cdc,14144
|
|
7
|
+
memwal/utils.py,sha256=RYlELBpKUHN9RuvWQu0cSGMoyXpAdTWlNKawfDpDbQ0,13361
|
|
8
|
+
memwal-0.2.2.dev4.dist-info/METADATA,sha256=qlEbcZYtZStlbKELvyf3pWaF1446Uxvd0VcZ6Hqw0Mo,12151
|
|
9
|
+
memwal-0.2.2.dev4.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
10
|
+
memwal-0.2.2.dev4.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
memwal/__init__.py,sha256=9xGvu4OTUpHjju77Hlwd8qb6oDjc6qvfQKM5nFQ1aU0,3142
|
|
2
|
-
memwal/client.py,sha256=3FBM1AP-YYoYPOzZFAeUA_nAYZtHWnTEuJWIdYThVas,97328
|
|
3
|
-
memwal/compatibility.py,sha256=FsKApCcHOFZeIeNOph3YydWVnZtMJdT0KCt0e6jylho,2799
|
|
4
|
-
memwal/middleware.py,sha256=z2xdbvaobBg4byJXnrX7amWdVYE4jfeO4t31DoDBv_o,38413
|
|
5
|
-
memwal/mock.py,sha256=JrYAkvEk_vkDDHd5RMWdyAqdE72GEgqFPlPbAFzZvkA,24347
|
|
6
|
-
memwal/types.py,sha256=yPNAEIGPY3O1GiFln0zW8stTPuV5sZYXAyQqeIkdbhw,13990
|
|
7
|
-
memwal/utils.py,sha256=RYlELBpKUHN9RuvWQu0cSGMoyXpAdTWlNKawfDpDbQ0,13361
|
|
8
|
-
memwal-0.2.2.dev3.dist-info/METADATA,sha256=WjL3FwG7QR-MjLPYJcPUHFGPIVVGjngRp3hnltvuNek,11911
|
|
9
|
-
memwal-0.2.2.dev3.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
10
|
-
memwal-0.2.2.dev3.dist-info/RECORD,,
|
|
File without changes
|