- /stats: corpus ad-stripping impact + per-account listening summary - Per-show "chapters" mode: mark ads as Podcasting-2.0 <podcast:chapters> instead of cutting; honored in the recommendation feed as well - /feeds.opml: bulk export of all subscribable feed URLs - /search genre filter across topics, episode titles, and transcripts - Share the episode->genre predicate (queries.episode_in_genre) and the cut-vs-chapters enclosure resolution across both feed builders
61 lines
2.1 KiB
TOML
61 lines
2.1 KiB
TOML
[project]
|
|
name = "hark"
|
|
version = "0.35.0"
|
|
description = "Cross-podcast topic index and discovery service"
|
|
readme = "README.md"
|
|
requires-python = ">=3.12"
|
|
dependencies = [
|
|
"anthropic>=0.116.0",
|
|
"feedparser>=6.0.11",
|
|
"httpx>=0.28",
|
|
"feedgen>=1.0.0",
|
|
"adscrub",
|
|
]
|
|
|
|
# adscrub does ad-detection/transcription/cutting as its own standalone product; hark
|
|
# depends on it as a library for the reusable, schema-agnostic pieces (chapter-JSON
|
|
# parsing, keep-span math, ffmpeg cutting, Whisper model loading, the Claude ad-span
|
|
# detector) rather than duplicating that code. hark's own glue
|
|
# (chapters.py/transcribe.py/detect.py/cut.py) wires those into hark's shows/episodes
|
|
# schema — see docs/PLAN.md.
|
|
#
|
|
# A git source, not a sibling path: a `../adscrub` path dependency made a fresh clone
|
|
# unbuildable and CI un-passable for anyone but the author. uv.lock pins the exact commit,
|
|
# so builds stay reproducible. To develop the two side by side, override with an editable
|
|
# install after syncing: uv sync && uv pip install -e ../adscrub
|
|
[tool.uv.sources]
|
|
adscrub = { git = "https://github.com/sudolulo/adscrub.git", branch = "main" }
|
|
|
|
[project.scripts]
|
|
hark = "hark.cli:main"
|
|
|
|
[project.optional-dependencies]
|
|
# Passes through to adscrub's own gpu extra (cuBLAS/cuDNN for faster-whisper's
|
|
# CUDA path) rather than duplicating that package list here.
|
|
gpu = [
|
|
"adscrub[gpu]",
|
|
]
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"pytest>=8.3",
|
|
"pyright>=1.1.400",
|
|
]
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
|
|
[tool.pyright]
|
|
# src/ only, not tests/: pyright's basic mode flags every resp.getheader(...)
|
|
# (typed Optional[str] by http.client's own stubs) that a test then calls
|
|
# .split()/uses `in` on without an assert — dozens of instances, each one
|
|
# harmless (a test that already asserted resp.status == 200 knows the header
|
|
# is there). Asserting it explicitly at every call site would be pure
|
|
# boilerplate, not a real safety gain; src/ itself is where a None slipping
|
|
# through actually matters, and it's already clean at "basic" strictness.
|
|
include = ["src"]
|