memorysync 1.7.0__tar.gz → 1.7.2__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.
@@ -43,6 +43,24 @@ htmlcov/
43
43
  *.cover
44
44
  out/
45
45
  /dashboard/tsconfig.tsbuildinfo
46
-
47
- # Responsive audit output (regenerated by npm run audit:responsive)
46
+
47
+ # Responsive audit output (regenerated by npm run audit:responsive)
48
48
  dashboard/responsive-audit-report.json
49
+
50
+ # -------------------------
51
+ # Category 4: Local worktrees and deploy clones (NEVER COMMIT)
52
+ # -------------------------
53
+ # Each of these holds its own .git directory. Staging one would record a
54
+ # gitlink with no matching .gitmodules entry, which reads as a broken
55
+ # submodule for everyone who clones afterwards, and it would drag several
56
+ # thousand unrelated files in with it.
57
+ #
58
+ # They are also why `git add .` stalls here rather than finishing: the walk
59
+ # has to touch roughly two thousand extra files, and because this repo lives
60
+ # under OneDrive, each one can trigger a hydration download before git is
61
+ # allowed to read it.
62
+ /.kiro/worktrees/
63
+ /.production-deploy/
64
+ /.baseline-int/
65
+ /.baseline-plan/
66
+ /.baseline-s3/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: memorysync
3
- Version: 1.7.0
3
+ Version: 1.7.2
4
4
  Summary: Official Python client for the MemorySync API.
5
5
  Project-URL: Homepage, https://memorysync.io
6
6
  Project-URL: Documentation, https://docs.memorysync.io
@@ -4,7 +4,10 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "memorysync"
7
- version = "1.7.0"
7
+ # Sourced from src/memorysync/_version.py rather than written here, so the
8
+ # packaged version and the one the library reports cannot disagree. They did:
9
+ # 1.7.1 went to PyPI while __version__ and the User-Agent both still said 1.7.0.
10
+ dynamic = ["version"]
8
11
  description = "Official Python client for the MemorySync API."
9
12
  readme = "README.md"
10
13
  license = { text = "MIT" }
@@ -50,6 +53,9 @@ Changelog = "https://docs.memorysync.io/release-notes"
50
53
  Support = "https://docs.memorysync.io/debugging/support"
51
54
  Status = "https://status.memorysync.io"
52
55
 
56
+ [tool.hatch.version]
57
+ path = "src/memorysync/_version.py"
58
+
53
59
  [tool.hatch.build.targets.wheel]
54
60
  packages = ["src/memorysync"]
55
61
 
@@ -0,0 +1 @@
1
+ __version__ = "1.7.2"
@@ -488,8 +488,9 @@ class MemorySyncClient:
488
488
  payload = filters.to_dict() if isinstance(filters, ForgetFilters) else dict(filters or {})
489
489
  if not payload:
490
490
  raise ValidationError(
491
- "filters must set at least one criterion; use purge_user() to "
492
- "remove everything for an end user"
491
+ "filters must set at least one criterion; to remove everything "
492
+ "for an end user use a wide criterion such as "
493
+ '{"before": datetime.now(timezone.utc)}'
493
494
  )
494
495
  body["filters"] = payload
495
496
  if dry_run:
@@ -628,13 +629,44 @@ class MemorySyncClient:
628
629
  return BatchUpdateResponse.from_dict(raw or {})
629
630
 
630
631
  def purge_user(self) -> Dict[str, Any]:
631
- """Delete every memory belonging to the calling end user.
632
-
633
- Separate from ``forget`` on purpose: this reads like what it does, so a
634
- whole-namespace delete can never be the accidental result of an empty
635
- filter.
632
+ """Not a memory operation, and not callable from this SDK. Always raises.
633
+
634
+ .. warning::
635
+
636
+ ``DELETE /memory/user/purge`` reads as if it clears one end user's
637
+ memories. It does neither. It ignores ``end_user_id`` and erases the
638
+ **account** behind the credential, cascading to the password hash,
639
+ every API key, memberships, auth providers and MFA credentials.
640
+ Nobody can sign in afterwards, and the API cannot repair it, because
641
+ the credential that would authorise a repair is one of the things it
642
+ destroys.
643
+
644
+ Earlier versions of this method described it as "delete every memory
645
+ belonging to the calling end user", and callers who believed that lost
646
+ accounts.
647
+
648
+ The server now refuses account erasure for every API-key caller, and
649
+ this client authenticates only with an API key, so the call could never
650
+ succeed. It raises locally rather than sending a request that can only
651
+ come back 403, so the reason arrives immediately and no destructive
652
+ intent leaves the process. Erase an account from the dashboard, where a
653
+ human is present.
654
+
655
+ :raises ValidationError: Always.
656
+
657
+ .. deprecated::
658
+ Use :meth:`forget` for anything memory related: by ids, or with a
659
+ wide criterion such as ``{"before": datetime.now(timezone.utc)}``.
636
660
  """
637
- return self._request("DELETE", "/memory/user/purge") or {}
661
+ raise ValidationError(
662
+ "purge_user() erases the whole account, not its memories: the password "
663
+ "hash, every API key and all sign-in credentials go with it. The API "
664
+ "refuses this for API-key callers, and this client only supports API "
665
+ "keys, so the call cannot succeed. To delete memories use forget(), "
666
+ "either with ids or a wide criterion such as "
667
+ '{"before": datetime.now(timezone.utc)}. To close an account, use the '
668
+ "dashboard."
669
+ )
638
670
 
639
671
  # ── History and feedback ─────────────────────────────────────────
640
672
 
@@ -1149,8 +1181,9 @@ class AsyncMemorySyncClient:
1149
1181
  payload = filters.to_dict() if isinstance(filters, ForgetFilters) else dict(filters or {})
1150
1182
  if not payload:
1151
1183
  raise ValidationError(
1152
- "filters must set at least one criterion; use purge_user() to "
1153
- "remove everything for an end user"
1184
+ "filters must set at least one criterion; to remove everything "
1185
+ "for an end user use a wide criterion such as "
1186
+ '{"before": datetime.now(timezone.utc)}'
1154
1187
  )
1155
1188
  body["filters"] = payload
1156
1189
  if dry_run:
@@ -1267,8 +1300,22 @@ class AsyncMemorySyncClient:
1267
1300
  return BatchUpdateResponse.from_dict(raw or {})
1268
1301
 
1269
1302
  async def purge_user(self) -> Dict[str, Any]:
1270
- """Async twin of :meth:`MemorySyncClient.purge_user`."""
1271
- return await self._request("DELETE", "/memory/user/purge") or {}
1303
+ """Async twin of :meth:`MemorySyncClient.purge_user`. Always raises.
1304
+
1305
+ Erases the **account**, not memories. Read the warning on the sync
1306
+ method before reaching for this.
1307
+
1308
+ :raises ValidationError: Always.
1309
+ """
1310
+ raise ValidationError(
1311
+ "purge_user() erases the whole account, not its memories: the password "
1312
+ "hash, every API key and all sign-in credentials go with it. The API "
1313
+ "refuses this for API-key callers, and this client only supports API "
1314
+ "keys, so the call cannot succeed. To delete memories use forget(), "
1315
+ "either with ids or a wide criterion such as "
1316
+ '{"before": datetime.now(timezone.utc)}. To close an account, use the '
1317
+ "dashboard."
1318
+ )
1272
1319
 
1273
1320
  # ── History and feedback ─────────────────────────────────────────
1274
1321
 
@@ -243,7 +243,12 @@ class ForgetFilters:
243
243
 
244
244
  At least one field must be set. An all-empty filter would mean "delete
245
245
  everything I own", and the server refuses it — that has to be an explicit
246
- request (``purge_user``) rather than the result of forgetting a field.
246
+ request rather than the result of forgetting a field.
247
+
248
+ To clear everything for an end user, say so with a wide criterion such as
249
+ ``{"before": datetime.now(timezone.utc)}``. Not ``purge_user``: an earlier
250
+ version of this docstring pointed there, and it erases the account rather
251
+ than its memories.
247
252
 
248
253
  ``tags`` matches memories carrying **all** the listed tags, not any of them.
249
254
  """
@@ -1 +0,0 @@
1
- __version__ = "1.7.0"
File without changes
File without changes