-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpyproject.toml
More file actions
193 lines (180 loc) · 6.71 KB
/
pyproject.toml
File metadata and controls
193 lines (180 loc) · 6.71 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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "stackunderflow"
version = "0.9.1"
description = "A local-first knowledge base for your AI coding sessions"
readme = "README.md"
requires-python = ">=3.11"
license = "MIT"
authors = [
{ name = "StackUnderflow Contributors" },
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"fastapi>=0.100.0",
"uvicorn[standard]>=0.23.0",
"click>=8.0.0",
"python-dotenv>=1.0.0",
"httpx>=0.24.0",
"uvloop>=0.17.0;sys_platform!='win32'",
"winloop>=0.1.8;sys_platform=='win32'",
"python-multipart>=0.0.6",
"orjson>=3.9.0",
"rich>=13.0.0",
# Wave 2C ETL filesystem watcher (Rust-backed; sub-100ms latency).
"watchfiles>=0.21.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=4.0.0",
"psutil>=5.9.0",
"ruff>=0.1.0",
"mypy>=1.5.0",
"types-python-dateutil",
"types-psutil",
"build>=1.0.0",
"twine>=4.0.0",
]
# Opt-in semantic search for ``search-past-decisions --use-embeddings``
# (HANDOFF #10). Pulls in sentence-transformers + its torch / numpy
# transitives. Heavy install — left out of the base deps so users who
# never flag ``--use-embeddings`` don't pay the ~500 MB cost.
embeddings = [
"sentence-transformers>=2.7,<3",
]
[project.scripts]
stackunderflow = "stackunderflow.cli:cli"
[project.urls]
Homepage = "https://github.com/0bserver07/StackUnderflow"
Repository = "https://github.com/0bserver07/StackUnderflow"
Issues = "https://github.com/0bserver07/StackUnderflow/issues"
Documentation = "https://0bserver07.github.io/StackUnderflow/"
Changelog = "https://github.com/0bserver07/StackUnderflow/blob/main/CHANGELOG.md"
[tool.hatch.build.targets.wheel]
packages = ["stackunderflow"]
# Auto-generated skills (`stackunderflow skills generate`) are *project-local*
# artifacts written to `<project>/.claude/skills/auto-*/SKILL.md` and mined
# from a user's private session store. They must NEVER end up in a release
# artifact — this is a hard constraint (see the auto-generated-skills spec),
# the surface where an implicit broadening would leak user data into a wheel.
# The skills shipped *with* the package live under `stackunderflow/skills/`
# (none of them are `auto-*`), so this is belt-and-suspenders, but it survives
# someone restructuring the package layout or dogfooding `skills generate`
# from inside this repo.
exclude = [
"**/auto-*/SKILL.md",
"**/.claude/skills/auto-*",
]
[tool.hatch.build.targets.sdist]
exclude = [
"stackunderflow-ui/",
"tests/",
".github/",
# never package auto-generated skills (see the wheel target above)
"**/auto-*/SKILL.md",
"**/.claude/skills/auto-*",
".claude/",
]
[tool.ruff]
line-length = 120
target-version = "py311"
exclude = [
"venv/",
"htmlcov/",
".pytest_cache/",
"__pycache__/",
"build/",
"dist/",
]
[tool.ruff.lint]
select = ["E", "F", "I", "N", "UP", "S", "B", "A", "C4", "T10", "T20"]
ignore = [
"S324", # Insecure hash functions - MD5 is used for cache keys, not security
]
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["T201", "S101"]
"test_*.py" = ["T201", "S101"]
"*_test.py" = ["T201", "S101"]
# Long regex patterns and SQL strings
"stackunderflow/services/tag_service.py" = ["E501"]
# rsync backup uses subprocess with constrained args, not user input
"stackunderflow/cli.py" = ["S603", "S607"]
# FTS queries use parameterised values; the f-string only assembles the
# fixed `column = ?` skeleton from a hardcoded clause list
"stackunderflow/services/qa_service.py" = ["S608"]
"stackunderflow/services/search_service.py" = ["S608"]
# Pricing service fetches a single hardcoded https URL from LiteLLM
"stackunderflow/services/pricing_service.py" = ["S310"]
# Currency module fetches a single hardcoded https URL from Frankfurter;
# isinstance(x, (int, float)) is the conventional numeric guard
"stackunderflow/infra/currency.py" = ["S310", "UP038"]
# isinstance(x, (int, float)) numeric guard in cost-conversion helper
"stackunderflow/routes/cost.py" = ["UP038"]
# `assert _cache is not None` is type-narrowing after a conditional init,
# not a runtime invariant we rely on
"stackunderflow/pipeline/history_reader.py" = ["S101"]
# `T = type(...)` is the conventional name for a type variable
"stackunderflow/settings.py" = ["N806"]
# `isinstance(x, (int, float))` is more readable than `int | float` here
"stackunderflow/infra/discovery.py" = ["UP038"]
# Mode-recommender feature dict has a "token_band" key whose values look
# like password constants to ruff (S105 false-positive on the token/secret
# keyword scan). The key name is part of the public payload — we suppress
# the warning rather than rename a contract.
"tests/stackunderflow/services/test_mode_recommender.py" = ["S105"]
# PR / CI webhook ingest (Spec 20): ENV_*_SECRET constants are env var
# *names*, not the secrets themselves. The S105 keyword scan flags any
# variable name containing "secret"; ruff has no way to distinguish a
# name-of-env-var from a literal credential.
"stackunderflow/routes/webhooks.py" = ["S105"]
# Meta-agent get_pr_outcomes / get_ci_runs build their WHERE clause from
# a fixed list of column-name = ? skeletons; values are always
# parameterised. Same posture as qa_service / search_service.
"stackunderflow/services/meta_agent.py" = ["S608"]
# Test fixtures pass throwaway tokens like "xyz" / "flag-token" /
# "ghp_fake" as fixture arguments — these are not real credentials.
"tests/stackunderflow/services/test_github_ingest.py" = ["S105", "S106"]
"tests/stackunderflow/cli/test_ingest_cli.py" = ["S105", "S106"]
[tool.pytest.ini_options]
# Custom markers. ``slow`` is opt-in: the default ``pytest tests/ -q`` run skips
# anything marked ``slow`` (see the ``-m "not slow"`` filter below) so CI keeps
# the fast feedback loop. The Wave 4E real-data integration + per-route
# regression suite under ``tests/stackunderflow/integration/`` is gated on this
# marker — run those explicitly with ``pytest -m slow``.
markers = [
"slow: long-running real-data integration / latency regression tests (skipped by default; run with `pytest -m slow`)",
]
addopts = "-m 'not slow'"
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
check_untyped_defs = true
exclude = [
"venv/",
"htmlcov/",
"tests/",
"setup.py",
]
[[tool.mypy.overrides]]
module = [
"dateutil.*",
"dotenv",
"fastapi.*",
"uvicorn.*",
"orjson",
"psutil",
]
ignore_missing_imports = true