mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
2f7ef136de
Branch builds testmon-select against cached baselines; 3-shard Postgres on 3.14 only; free runners; 120s hang ceiling; non-code changes skip the matrix; BM Bossbot and infographic machinery removed. Signed-off-by: phernandez <paul@basicmemory.com>
178 lines
5.8 KiB
TOML
178 lines
5.8 KiB
TOML
[project]
|
|
name = "basic-memory"
|
|
dynamic = ["version"]
|
|
description = "Local-first knowledge management combining Zettelkasten with knowledge graphs"
|
|
readme = "README.md"
|
|
requires-python = ">=3.12"
|
|
license = { text = "AGPL-3.0-or-later" }
|
|
authors = [
|
|
{ name = "Basic Machines", email = "hello@basic-machines.co" }
|
|
]
|
|
dependencies = [
|
|
"sqlalchemy>=2.0.0",
|
|
"pyyaml>=6.0.1",
|
|
"typer>=0.9.0",
|
|
"aiosqlite>=0.20.0",
|
|
"greenlet>=3.1.1",
|
|
"pydantic[email,timezone]>=2.12.0",
|
|
"mcp>=1.23.1",
|
|
"pydantic-settings>=2.6.1",
|
|
"loguru>=0.7.3",
|
|
"pyright>=1.1.390",
|
|
"markdown-it-py>=3.0.0",
|
|
"python-frontmatter>=1.1.0",
|
|
"rich>=13.9.4",
|
|
"unidecode>=1.3.8",
|
|
"dateparser>=1.2.0",
|
|
"watchfiles>=1.0.4",
|
|
"fastapi[standard]>=0.136.1",
|
|
"alembic>=1.14.1",
|
|
"pillow>=11.1.0",
|
|
"pybars3>=0.9.7",
|
|
# Keep FastMCP pinned until each minor upgrade passes the MCP transport matrix.
|
|
"fastmcp==3.3.1",
|
|
"pyjwt>=2.10.1",
|
|
"python-dotenv>=1.1.0",
|
|
"pytest-aio>=1.9.0",
|
|
"aiofiles>=24.1.0",
|
|
"asyncpg>=0.30.0",
|
|
"nest-asyncio>=1.6.0", # For Alembic migrations with Postgres
|
|
"pytest-asyncio>=1.2.0",
|
|
"psycopg==3.3.1",
|
|
"mdformat>=0.7.22",
|
|
"mdformat-gfm>=0.3.7",
|
|
"mdformat-frontmatter>=2.0.8",
|
|
"sniffio>=1.3.1",
|
|
"anyio>=4.10.0",
|
|
"httpx>=0.28.0",
|
|
"fastembed>=0.7.4",
|
|
"sqlite-vec>=0.1.6",
|
|
"openai>=1.100.2",
|
|
"litellm>=1.60.0,<2.0.0",
|
|
"logfire>=4.19.0",
|
|
"psutil>=5.9.0",
|
|
# uvloop's C event loop has no self._ready.popleft() codepath, so the
|
|
# asyncpg engine-dispose race ("IndexError: pop from an empty deque") that
|
|
# crashes the Postgres backend cannot fire under it. Not available on Windows.
|
|
"uvloop>=0.21.0; sys_platform != 'win32'",
|
|
]
|
|
|
|
[project.urls]
|
|
Homepage = "https://github.com/basicmachines-co/basic-memory"
|
|
Repository = "https://github.com/basicmachines-co/basic-memory"
|
|
Documentation = "https://github.com/basicmachines-co/basic-memory#readme"
|
|
|
|
[project.scripts]
|
|
basic-memory = "basic_memory.cli.main:app"
|
|
bm = "basic_memory.cli.main:app"
|
|
|
|
[build-system]
|
|
requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.pytest.ini_options]
|
|
pythonpath = ["src", "tests"]
|
|
addopts = "--cov=basic_memory --cov-report term-missing"
|
|
testpaths = ["tests", "test-int"]
|
|
asyncio_mode = "strict"
|
|
asyncio_default_fixture_loop_scope = "function"
|
|
# Any test hanging >120s fails with a stack dump instead of stalling the CI job
|
|
# until the runner times out (the FastMCP/asyncpg cleanup-hang family).
|
|
timeout = 120
|
|
timeout_method = "thread"
|
|
filterwarnings = [
|
|
"ignore:The @wait_container_is_ready decorator is deprecated.*:DeprecationWarning:testcontainers\\.core\\.waiting_utils",
|
|
"ignore:The default datetime adapter is deprecated as of Python 3\\.12.*:DeprecationWarning:aiosqlite\\.core",
|
|
"ignore:codecs\\.open\\(\\) is deprecated\\. Use open\\(\\) instead\\.:DeprecationWarning:frontmatter",
|
|
"ignore:Parsing dates involving a day of month without a year specified is ambiguous.*:DeprecationWarning:dateparser\\.utils\\.strptime",
|
|
]
|
|
markers = [
|
|
"benchmark: Performance benchmark tests (deselect with '-m \"not benchmark\"')",
|
|
"slow: Slow-running tests (deselect with '-m \"not slow\"')",
|
|
"postgres: Tests that run against Postgres backend (deselect with '-m \"not postgres\"')",
|
|
"windows: Windows-specific tests (deselect with '-m \"not windows\"')",
|
|
"smoke: Fast end-to-end smoke tests for MCP flows",
|
|
"semantic: Tests requiring semantic dependencies (fastembed, sqlite-vec, openai)",
|
|
"live: Tests that call external provider APIs and require explicit opt-in",
|
|
]
|
|
|
|
[tool.ruff]
|
|
line-length = 100
|
|
target-version = "py312"
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"logfire>=4.19.0",
|
|
"gevent>=24.11.1",
|
|
"icecream>=2.1.3",
|
|
"pytest>=8.3.4",
|
|
"pytest-cov>=4.1.0",
|
|
"pytest-mock>=3.12.0",
|
|
"pytest-asyncio>=0.24.0",
|
|
"pytest-xdist>=3.0.0",
|
|
"ruff>=0.1.6",
|
|
"freezegun>=1.5.5",
|
|
"testcontainers[postgres]>=4.0.0",
|
|
"psycopg>=3.2.0",
|
|
"pyright>=1.1.408",
|
|
"pytest-testmon>=2.2.0",
|
|
"ty>=0.0.18",
|
|
"cst-lsp>=0.1.3",
|
|
"libcst>=1.8.6",
|
|
"pytest-timeout>=2.4.0",
|
|
"pytest-split>=0.11.0",
|
|
]
|
|
|
|
[tool.hatch.version]
|
|
source = "uv-dynamic-versioning"
|
|
|
|
[tool.uv-dynamic-versioning]
|
|
vcs = "git"
|
|
style = "pep440"
|
|
bump = true
|
|
fallback-version = "0.0.0"
|
|
|
|
[tool.pyright]
|
|
include = ["src/"]
|
|
exclude = ["**/__pycache__"]
|
|
ignore = ["test/"]
|
|
defineConstant = { DEBUG = true }
|
|
reportMissingImports = "error"
|
|
reportMissingTypeStubs = false
|
|
reportUnusedImport = "none"
|
|
pythonVersion = "3.12"
|
|
|
|
|
|
|
|
[tool.coverage.run]
|
|
concurrency = ["thread", "gevent"]
|
|
parallel = true
|
|
source = ["basic_memory"]
|
|
|
|
[tool.coverage.report]
|
|
exclude_lines = [
|
|
"pragma: no cover",
|
|
"def __repr__",
|
|
"if self.debug:",
|
|
"if settings.DEBUG",
|
|
"raise AssertionError",
|
|
"raise NotImplementedError",
|
|
"if 0:",
|
|
"if __name__ == .__main__.:",
|
|
"class .*\\bProtocol\\):",
|
|
"@(abc\\.)?abstractmethod",
|
|
]
|
|
|
|
# Exclude specific modules that are difficult to test comprehensively
|
|
omit = [
|
|
"*/external_auth_provider.py", # External HTTP calls to OAuth providers
|
|
"*/supabase_auth_provider.py", # External HTTP calls to Supabase APIs
|
|
"*/watch_service.py", # File system watching - complex integration testing
|
|
"*/background_sync.py", # Background processes
|
|
"*/cli/**", # CLI is an interactive wrapper; core logic is covered via API/MCP/service tests
|
|
"*/db.py", # Backend/runtime-dependent (sqlite/postgres/windows tuning); validated via integration tests
|
|
"*/services/initialization.py", # Startup orchestration + background tasks (watchers); exercised indirectly in entrypoints
|
|
"*/sync/sync_service.py", # Heavy filesystem/db integration; covered by integration suite, not enforced in unit coverage
|
|
"*/services/migration_service.py", # Complex migration scenarios
|
|
]
|