-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
131 lines (121 loc) · 5.47 KB
/
Copy pathpyproject.toml
File metadata and controls
131 lines (121 loc) · 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
[project]
name = "studyloop-workspace"
# Must equal packages/studyloop/pyproject.toml's version -- enforced by
# scripts/check-release-consistency.py (R-39; this drifted to 1.0.0 while the
# package sat at 0.1.0, unnoticed because the script never read this file).
version = "0.5.0"
description = "StudyLoop: AuDHD-aware Socratic mentoring with AI session management"
requires-python = ">=3.12"
readme = "README.md"
license = "MIT"
authors = [{name = "Andy Taylor"}]
dependencies = [
"fastapi>=0.135.1",
"kokoro-onnx>=0.5.0",
"pexpect>=4.9.0",
"pyyaml>=6.0.3",
"sentence-transformers>=5.2.3",
]
[project.optional-dependencies]
docs = [
"mkdocs>=1.6,<2",
"mkdocs-material>=9.5,<10",
"pymdown-extensions>=10",
]
[dependency-groups]
dev = [
"pytest>=9.0",
"pytest-cov>=7.0",
"ruff>=0.8",
"pyright>=1.1",
"pre-commit>=4.0",
"httpx>=0.28.1",
# Starlette 1.3's TestClient prefers the successor package and emits a
# deprecation warning when only legacy httpx is installed. Pinned exactly
# because this is a new dependency with an independent major-version line.
"httpx2==2.12.0",
"pexpect>=4.9.0",
"textual>=8.0.2",
"pytest-asyncio>=1.3.0",
"pytest-playwright>=0.7.2",
# A test that blocks forever is worse than one that fails: a single
# unbounded WebSocket receive (TestClient has no receive timeout) hung the
# whole 3,593-test suite with no summary and no named culprit. A per-test
# timeout turns any such hang into an ordinary, attributable failure.
"pytest-timeout>=2.3",
"respx>=0.23.1",
"mcp[cli]>=1.0.0,<2",
"bandit>=1.8",
"pymupdf>=1.25",
"notebooklm-py>=0.3.4",
# boto3 powers the Bedrock content generator (studyloop[bedrock]). It is
# in the dev group so a plain `uv sync` gives `uv run studyloop web` a
# working Bedrock backend — otherwise generation dies with
# "No module named 'boto3'" because workspace members are synced without
# their optional-dependencies.
"boto3>=1.40",
]
[build-system]
requires = ["setuptools>=75"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
py-modules = [] # Workspace root — no packages to install here
[tool.uv.workspace]
members = ["packages/*"]
[tool.ruff]
target-version = "py312"
line-length = 100
[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP", "B", "A", "C4", "SIM", "TCH", "RUF"]
[tool.ruff.lint.isort]
known-first-party = ["studyloop", "agent_session_tools"]
[tool.pyright]
pythonVersion = "3.12"
typeCheckingMode = "basic"
include = [
"packages/studyloop/src",
"packages/studyloop/tests",
"packages/agent-session-tools/src",
"packages/agent-session-tools/tests",
]
exclude = [
"packages/agent-session-tools/tests/test_embeddings.py",
"scripts/capture_tui_screenshot.py",
"scripts/record-demo.py",
]
[tool.pytest.ini_options]
testpaths = ["packages/agent-session-tools/tests", "packages/studyloop/tests"]
addopts = "--import-mode=importlib -m 'not integration and not e2e and not live_kiro and not live_provider and not live_obsidian and not live_xtiles and not acceptance and not uat'"
# Multi-package workspace: both packages/studyloop/tests/ and
# packages/agent-session-tools/tests/ have their own conftest.py.
# Without this, pytest's plugin manager tries to register both under
# the same implicit name "tests.conftest" and fails with
# "Plugin already registered under a different name".
consider_namespace_packages = true
# Per-test wall-clock ceiling. Generous on purpose: the slowest legitimate unit
# test (test_sidebar_pilot) takes ~13s, so 60s only ever fires on a genuine
# hang. Without it an unbounded TestClient WebSocket receive blocks the run
# forever and no summary is ever printed.
#
# NOTE this bounds UNIT tests. e2e tests routinely need longer -- a real browser
# plus a subprocess server, with individual waits already allowing 60-180s -- so
# they carry an explicit `pytestmark = pytest.mark.timeout(...)` per module. A
# bare 60s would kill them before their own deadlines.
timeout = 60
# "signal" (SIGALRM), not "thread": the hang this guards against is a blocked
# selector inside a TestClient WebSocket receive, and a timer thread cannot
# interrupt that — verified, "thread" let it hang indefinitely while "signal"
# turned it into a normal failure. SIGALRM is POSIX-only, which matches the
# project's supported platforms (macOS primary, Linux secondary).
timeout_method = "signal"
markers = [
"integration: requires external infrastructure (tmux, real DB, network)",
"e2e: end-to-end tests requiring full stack (tmux, ttyd, web server)",
"live_kiro: dogfood tests that spawn a real kiro-cli acp child",
"live_provider: tests that call a real LLM provider",
"live_obsidian: tests that write into a dedicated throwaway Obsidian vault on the owner's machine and read the notes back (opt in with -m live_obsidian)",
"live_xtiles: opt-in Playwright checks against the owner's real xTiles account, validating in the UI what an assistant wrote through the MCP connector (needs a one-time sign-in; opt in with -m live_xtiles)",
"allow_server_errors: test deliberately drives the server into an unhandled exception, so the per-test server-log check is skipped for it",
"acceptance: opt-in acceptance tier (STUDYLOOP_ACC=1 -- see docs/acceptance-testing.md); skipped by default, run via `just testacc`",
"uat: opt-in UAT sign-off tier (STUDYLOOP_ACC=1 AND STUDYLOOP_UAT=1 -- see docs/acceptance-testing.md); its own opt-in on top of acceptance, run via `just testuat`",
]