basic-memory 0.23.2.dev3__py3-none-any.whl → 0.23.3.dev1__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.
- basic_memory/__init__.py +1 -1
- basic_memory/alembic/env.py +8 -18
- basic_memory/deps/config.py +5 -1
- basic_memory/deps/read_cache.py +6 -2
- {basic_memory-0.23.2.dev3.dist-info → basic_memory-0.23.3.dev1.dist-info}/METADATA +1 -2
- {basic_memory-0.23.2.dev3.dist-info → basic_memory-0.23.3.dev1.dist-info}/RECORD +9 -10
- basic_memory/migration_loop.py +0 -34
- {basic_memory-0.23.2.dev3.dist-info → basic_memory-0.23.3.dev1.dist-info}/WHEEL +0 -0
- {basic_memory-0.23.2.dev3.dist-info → basic_memory-0.23.3.dev1.dist-info}/entry_points.txt +0 -0
- {basic_memory-0.23.2.dev3.dist-info → basic_memory-0.23.3.dev1.dist-info}/licenses/LICENSE +0 -0
basic_memory/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
|
|
2
2
|
|
|
3
3
|
# Package version - updated by release automation
|
|
4
|
-
__version__ = "0.23.
|
|
4
|
+
__version__ = "0.23.2"
|
|
5
5
|
|
|
6
6
|
# API version for FastAPI - independent of package version
|
|
7
7
|
__api_version__ = "v2"
|
basic_memory/alembic/env.py
CHANGED
|
@@ -2,34 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import os
|
|
5
|
-
import sys
|
|
6
5
|
from contextlib import suppress
|
|
7
6
|
from logging.config import fileConfig
|
|
8
7
|
|
|
9
|
-
from loguru import logger
|
|
10
8
|
from sqlalchemy import engine_from_config, pool
|
|
11
9
|
from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
12
10
|
|
|
13
11
|
from alembic import context
|
|
14
12
|
|
|
15
13
|
from basic_memory.config import ConfigManager
|
|
16
|
-
from basic_memory.migration_loop import running_on_uvloop
|
|
17
14
|
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
nest_asyncio.apply()
|
|
27
|
-
except (ImportError, ValueError) as exc:
|
|
28
|
-
# Trigger: nest_asyncio is absent (ImportError) or refuses to patch the
|
|
29
|
-
# running loop (ValueError).
|
|
30
|
-
# Outcome: log at DEBUG (observable, not noisy) and fall through to the
|
|
31
|
-
# thread-based migration fallback.
|
|
32
|
-
logger.debug(f"nest_asyncio not applied ({exc!r}); using thread-based migration fallback")
|
|
15
|
+
# Constraint: never apply nest_asyncio here. It replaces asyncio.run and
|
|
16
|
+
# run_until_complete process-wide, and its run_until_complete returns the moment
|
|
17
|
+
# the root task finishes without running that task's done-callbacks. anyio stops
|
|
18
|
+
# its worker threads from exactly such a callback, so any request that touched
|
|
19
|
+
# the thread pool left a non-daemon worker parked forever and one-shot CLI
|
|
20
|
+
# commands hung at interpreter exit on Python < 3.14 (#1333, #1345). Callers
|
|
21
|
+
# already inside a running loop (pytest-asyncio, the API lifespan) take the
|
|
22
|
+
# thread fallback in run_migrations_online(), the only path 3.14 ever used.
|
|
33
23
|
|
|
34
24
|
# Trigger: only set test env when actually running under pytest
|
|
35
25
|
# Why: alembic/env.py is imported during normal operations (MCP server startup, migrations)
|
basic_memory/deps/config.py
CHANGED
|
@@ -12,12 +12,16 @@ from fastapi import Depends, Request
|
|
|
12
12
|
from basic_memory.config import BasicMemoryConfig
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def get_app_config(request: Request) -> BasicMemoryConfig:
|
|
15
|
+
async def get_app_config(request: Request) -> BasicMemoryConfig:
|
|
16
16
|
"""Resolve the application configuration from the composition root.
|
|
17
17
|
|
|
18
18
|
API requests read the container the lifespan stored on ``app.state``.
|
|
19
19
|
Requests served without a lifespan (the CLI/MCP local ASGI flow) fall back
|
|
20
20
|
to the API composition root, which creates a container on demand.
|
|
21
|
+
|
|
22
|
+
Declared ``async`` although it never awaits: FastAPI runs *sync* dependencies
|
|
23
|
+
on anyio's worker-thread pool, and an attribute read is not worth a thread
|
|
24
|
+
hop per request — nor the non-daemon worker it leaves parked (#1345).
|
|
21
25
|
"""
|
|
22
26
|
container = getattr(request.app.state, "container", None)
|
|
23
27
|
if container is not None:
|
basic_memory/deps/read_cache.py
CHANGED
|
@@ -12,8 +12,12 @@ from basic_memory.read_cache.policy import (
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def get_read_cache(request: Request) -> ReadCache | None:
|
|
16
|
-
"""Return the optional host-injected cache backend.
|
|
15
|
+
async def get_read_cache(request: Request) -> ReadCache | None:
|
|
16
|
+
"""Return the optional host-injected cache backend.
|
|
17
|
+
|
|
18
|
+
``async`` for the same reason as ``get_app_config``: a sync dependency would
|
|
19
|
+
hop to anyio's worker pool just to read an attribute (#1345).
|
|
20
|
+
"""
|
|
17
21
|
try:
|
|
18
22
|
container = request.app.state.container
|
|
19
23
|
except AttributeError:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: basic-memory
|
|
3
|
-
Version: 0.23.
|
|
3
|
+
Version: 0.23.3.dev1
|
|
4
4
|
Summary: Local-first knowledge management combining Zettelkasten with knowledge graphs
|
|
5
5
|
Project-URL: Homepage, https://github.com/basicmachines-co/basic-memory
|
|
6
6
|
Project-URL: Repository, https://github.com/basicmachines-co/basic-memory
|
|
@@ -29,7 +29,6 @@ Requires-Dist: mcp<3,>=2
|
|
|
29
29
|
Requires-Dist: mdformat-frontmatter>=2.0.8
|
|
30
30
|
Requires-Dist: mdformat-gfm>=0.3.7
|
|
31
31
|
Requires-Dist: mdformat>=0.7.22
|
|
32
|
-
Requires-Dist: nest-asyncio>=1.6.0
|
|
33
32
|
Requires-Dist: openai>=1.100.2
|
|
34
33
|
Requires-Dist: pillow>=11.1.0
|
|
35
34
|
Requires-Dist: psutil>=5.9.0
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
basic_memory/__init__.py,sha256=
|
|
1
|
+
basic_memory/__init__.py,sha256=dtmjVy3Q4_DYddSDwS9XOq3okErGMfYtVZ-_1s5p2zQ,256
|
|
2
2
|
basic_memory/config.py,sha256=gPw1piQZJANYCF-TkpEpc9-vD7-lHnSez8HQidGh5qk,12080
|
|
3
3
|
basic_memory/config_logging.py,sha256=keqWv5xPOP6fjh1LDQmKMDyduHTYAhr6Y1EKiiYVDnc,1857
|
|
4
4
|
basic_memory/config_migrations.py,sha256=OO5hwzs3x5EEix-jNMeETrJQwMx0l2iHUywXRLMjzFA,3582
|
|
@@ -6,14 +6,13 @@ basic_memory/config_models.py,sha256=TehggqA0vm9eVo9rQugAXyTmQ-R_BJVriNl8niMiVw0
|
|
|
6
6
|
basic_memory/db.py,sha256=STYA6RmCWXFaF3ZhC0_ay0Q8B2V_htrOFo6YQcW528Q,25977
|
|
7
7
|
basic_memory/file_utils.py,sha256=_cIrb3xebx2wDdoHvvIWWgA9yfePc4TDuAAnks3Dges,18540
|
|
8
8
|
basic_memory/ignore_utils.py,sha256=1OoKxiS7_ofYYHWTtH5zoUVeaMJ8-V7j0dsqxYA3dDo,8486
|
|
9
|
-
basic_memory/migration_loop.py,sha256=KGhuCLgrgwW21GAGT9cOczbtRlM4mGi7aUBjG1shQ8s,1609
|
|
10
9
|
basic_memory/project_resolver.py,sha256=vHWHw1X9_1IqtX9Dy5yNXqNRas3wcrpQJVKxJuj4qWg,3801
|
|
11
10
|
basic_memory/redaction.py,sha256=tYolNeRQdOfcELD9sGtzQbB5dS3odP9PAnzipqmMl6M,4804
|
|
12
11
|
basic_memory/telemetry.py,sha256=pAkPgbAOmivZDkCAW0S2CKSNw4AqBfMckdsbb2EipcQ,1721
|
|
13
12
|
basic_memory/utils.py,sha256=bXlhv3qHOO_1Lb_2gUspjOZ3H1-qgreWl_n5eR6_Jxg,35426
|
|
14
13
|
basic_memory/workspace_context.py,sha256=v-u4jO8VFB1WeFZ1UpzZnbf9ph71vvz1OMibpAtrtQI,3648
|
|
15
14
|
basic_memory/alembic/alembic.ini,sha256=IEZsnF8CbbZnkwBr67LzKKNobHuzTaQNUvM8Psop5xc,3733
|
|
16
|
-
basic_memory/alembic/env.py,sha256=
|
|
15
|
+
basic_memory/alembic/env.py,sha256=26K_F2KEvz3SneUQ5LuHCpvZ1FD1w9s1wP63lQFDNZI,9275
|
|
17
16
|
basic_memory/alembic/migrations.py,sha256=lriHPXDdBLSNXEW3QTpU0SJKuVd1V-8NrVkpN3qfsUQ,718
|
|
18
17
|
basic_memory/alembic/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
|
|
19
18
|
basic_memory/alembic/versions/2d26b287813b_dedupe_observations_and_purge_stale_.py,sha256=h-Q0g5g2r3GmXWK49RyxvmvHGd5idVGA4VYkK4LYTek,2139
|
|
@@ -115,11 +114,11 @@ basic_memory/cli/commands/cloud/webdav.py,sha256=5yanr7lQy6dv8RVvixI0k_3HpCOnyzV
|
|
|
115
114
|
basic_memory/cli/commands/cloud/webdav_transfer.py,sha256=ncj_eLthaN7a8-eKyieBxHoBqg3SaXVXIs6K8_UGw2Q,23340
|
|
116
115
|
basic_memory/cli/commands/cloud/workspace.py,sha256=08TdcYohmDunprmUgpGO4SvCjD7A_vynBYIkD2LNooc,3940
|
|
117
116
|
basic_memory/deps/__init__.py,sha256=thQt1C04eNMA49Y3OubiIiv0WIWie75aCd4TBTMkddE,6139
|
|
118
|
-
basic_memory/deps/config.py,sha256=
|
|
117
|
+
basic_memory/deps/config.py,sha256=zQrYU7K6XIFflvi8VYFmbEhIJ5GDQXoqHZ9SFWoLKQg,1444
|
|
119
118
|
basic_memory/deps/db.py,sha256=xpD5Mcq16f8J0lbu8PCoRcr2s4e1xKOj1nze_NW3CGg,2395
|
|
120
119
|
basic_memory/deps/importers.py,sha256=G2ulW2xdexR4indqlNYqt9kzoQCtSqnPcRgb-ae4Cuo,3786
|
|
121
120
|
basic_memory/deps/projects.py,sha256=z2Qziv58GJw-I4CofIiIXeyXBVtYHAcd-dep5Fg2slw,3352
|
|
122
|
-
basic_memory/deps/read_cache.py,sha256=
|
|
121
|
+
basic_memory/deps/read_cache.py,sha256=l6yJCUWkW2kHhK80GqzPMSJDwEe6wqWFC7gOgJg_YY8,1559
|
|
123
122
|
basic_memory/deps/repositories.py,sha256=2ZQeScK-C3VOnYs_re0FCAty5cEz3PpTPnSxtW_gFqQ,2750
|
|
124
123
|
basic_memory/deps/services.py,sha256=cjxsFhVTwqmf-nUUv3SdEKM-UXBf8OH0oQ9Dj5HO7RY,21096
|
|
125
124
|
basic_memory/hooks/__init__.py,sha256=kEvNW8tpXcnTdzwUpjoir2RZxVXRULJhB38WGwDKCHc,861
|
|
@@ -391,8 +390,8 @@ basic_memory/services/search_service.py,sha256=8A1vXo5IIpKXL2gxEsCEP_tcKyRcnz4R5
|
|
|
391
390
|
basic_memory/services/service.py,sha256=V-d_8gOV07zGIQDpL-Ksqs3ZN9l3qf3HZOK1f_YNTag,336
|
|
392
391
|
basic_memory/templates/prompts/continue_conversation.hbs,sha256=trrDHSXA5S0JCbInMoUJL04xvCGRB_ku1RHNQHtl6ZI,3076
|
|
393
392
|
basic_memory/templates/prompts/search.hbs,sha256=H1cCIsHKp4VC1GrH2KeUB8pGe5vXFPqb2VPotypmeCA,3098
|
|
394
|
-
basic_memory-0.23.
|
|
395
|
-
basic_memory-0.23.
|
|
396
|
-
basic_memory-0.23.
|
|
397
|
-
basic_memory-0.23.
|
|
398
|
-
basic_memory-0.23.
|
|
393
|
+
basic_memory-0.23.3.dev1.dist-info/METADATA,sha256=wwkhjqSEcIvGTYO-Ct-6DWT4qddKDYgiVUxFQH-m-5g,26812
|
|
394
|
+
basic_memory-0.23.3.dev1.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
395
|
+
basic_memory-0.23.3.dev1.dist-info/entry_points.txt,sha256=wvE2mRF6-Pg4weIYcfQ-86NOLZD4WJg7F7TIsRVFLb8,90
|
|
396
|
+
basic_memory-0.23.3.dev1.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
397
|
+
basic_memory-0.23.3.dev1.dist-info/RECORD,,
|
basic_memory/migration_loop.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"""Pure helpers for how Alembic bridges async migrations across event loops.
|
|
2
|
-
|
|
3
|
-
Extracted from ``alembic/env.py`` so these two decisions are unit-testable:
|
|
4
|
-
env.py runs migrations at import time and cannot be imported in a test, but the
|
|
5
|
-
loop-detection and error-classification logic is exactly what regresses, so it
|
|
6
|
-
lives here where it can be covered directly.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
import asyncio
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def running_on_uvloop() -> bool:
|
|
15
|
-
"""Return True when the active asyncio policy is uvloop.
|
|
16
|
-
|
|
17
|
-
The Postgres backend installs the uvloop policy before the event loop starts
|
|
18
|
-
(#831/#877). nest_asyncio cannot patch a uvloop loop, but depending on the
|
|
19
|
-
nest_asyncio version ``apply()`` may NOT raise the ValueError we expect — it
|
|
20
|
-
can silently mis-patch the stdlib loop instead. The later ``asyncio.run()``
|
|
21
|
-
then fails with "this event loop is already running" rather than the standard
|
|
22
|
-
"cannot be called from a running event loop", which the thread-based fallback
|
|
23
|
-
would not recognize, crashing startup. Detecting uvloop up front lets env.py
|
|
24
|
-
skip nest_asyncio entirely and stay on the standard running-loop error path.
|
|
25
|
-
"""
|
|
26
|
-
try:
|
|
27
|
-
import uvloop
|
|
28
|
-
except ImportError:
|
|
29
|
-
return False
|
|
30
|
-
# Constraint: on supported Python 3.12-3.13 this helper runs before a loop
|
|
31
|
-
# exists, so the active policy is the only observable uvloop signal. Python
|
|
32
|
-
# 3.14+ skips this helper in alembic/env.py; remove it with the policy seam.
|
|
33
|
-
policy = asyncio.get_event_loop_policy() # ty: ignore[deprecated]
|
|
34
|
-
return isinstance(policy, uvloop.EventLoopPolicy)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|