Skip to content

Commit 04d57fc

Browse files
authored
build: add pyproject.toml and Python packaging infrastructure (closes #45) (#49)
* feat: add pyproject.toml and comments on requiremnts.txt * fix: add assets directories to project toml file. * fix: made pywebview for legacy install as optional. * fix: add an explicit constraint on Pillow to block known-vulnerable versions * fix: review comments * fix: Add an explicit Pillow constraint to exclude known-vulnerable versions.
1 parent 238de78 commit 04d57fc

4 files changed

Lines changed: 114 additions & 6 deletions

File tree

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
fail-fast: false
2828
matrix:
2929
os: [ubuntu-latest]
30-
python-version: ["3.11", "3.12", "3.13"]
30+
python-version: ["3.10", "3.11", "3.12", "3.13"]
3131
steps:
3232
# Pinned to immutable commit SHAs (not @v4 / @v5) so a compromised tag
3333
# cannot silently swap the underlying action code on this CI runner.

launcher.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55
directly in-process.
66
"""
77

8-
import webview
9-
108
from app import create_app
119

1210

1311
def main():
12+
try:
13+
import webview
14+
except ImportError:
15+
raise SystemExit(
16+
"pywebview is not installed. Install the [desktop] extra, e.g.\n"
17+
' pip install -e ".[desktop]"'
18+
) from None
19+
1420
app = create_app()
1521
webview.create_window(
1622
"Cursor Chat Browser",

pyproject.toml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
[build-system]
2+
requires = ["hatchling>=1.21"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "cppa-cursor-browser"
7+
version = "0.1.0"
8+
description = "Flask web application for browsing and exporting Cursor AI chat histories"
9+
readme = "README.md"
10+
license = { file = "LICENSE" }
11+
authors = [{ name = "C++ Alliance", email = "admin@cppalliance.org" }]
12+
requires-python = ">=3.10"
13+
14+
# Runtime dependencies — bounded on both sides so CI resolves deterministically
15+
# and breaking major releases are caught at install time rather than at runtime.
16+
# Upper bounds are conservative: pin to current known-compatible major version.
17+
# See also: requirements.txt (backward-compat alias; pyproject.toml is canonical).
18+
dependencies = [
19+
"flask>=3.0,<4",
20+
"fpdf2>=2.7,<3",
21+
# Security floor: fpdf2 allows Pillow>=8.3.2, so 9.x can still be resolved.
22+
# CVE-2024-28219 (buffer overflow) fixed in Pillow 10.3.0 — https://nvd.nist.gov/vuln/detail/CVE-2024-28219
23+
"pillow>=10.3.0",
24+
]
25+
26+
[project.optional-dependencies]
27+
# Desktop launcher (pywebview pulls in heavy system libs — GTK/Qt on Linux —
28+
# so it is intentionally excluded from the web-server and CI installs).
29+
desktop = ["pywebview>=5.0,<6"]
30+
31+
# Development tooling: testing + type checking.
32+
dev = [
33+
"pytest>=8,<9",
34+
"mypy>=1.10,<2",
35+
]
36+
37+
[project.scripts]
38+
# Primary CLI: export Cursor chat histories to Markdown / zip.
39+
# Usage: cursor-chat-export [--since all|last] [--out DIR] [--no-zip] [--help]
40+
cursor-chat-export = "scripts.export:main"
41+
42+
# Desktop launcher (requires the [desktop] extra to be installed).
43+
cursor-chat-browser = "launcher:main"
44+
45+
[project.urls]
46+
Repository = "https://github.com/cppalliance/cppa-cursor-browser"
47+
Issues = "https://github.com/cppalliance/cppa-cursor-browser/issues"
48+
49+
# ── Build configuration ────────────────────────────────────────────────────────
50+
# Flat layout (no src/ directory): enumerate every importable package and the
51+
# two top-level application modules so the installed wheel has the same import
52+
# surface as the repo checkout.
53+
[tool.hatch.build.targets.wheel]
54+
include = [
55+
"api/",
56+
"models/",
57+
"scripts/",
58+
"services/",
59+
"utils/",
60+
"templates/",
61+
"static/",
62+
"app.py",
63+
"launcher.py",
64+
]
65+
66+
# sdist includes tests + ancillary files; wheel is runtime-only.
67+
[tool.hatch.build.targets.sdist]
68+
include = [
69+
"api/",
70+
"models/",
71+
"scripts/",
72+
"services/",
73+
"utils/",
74+
"tests/",
75+
"templates/",
76+
"static/",
77+
"app.py",
78+
"launcher.py",
79+
"requirements.txt",
80+
"README.md",
81+
"LICENSE",
82+
"cursor-browser.spec",
83+
]
84+
85+
# ── Mypy ──────────────────────────────────────────────────────────────────────
86+
# Mirrors the flags used in .github/workflows/tests.yml so local `mypy .`
87+
# and CI produce identical results.
88+
[tool.mypy]
89+
ignore_missing_imports = true
90+
no_strict_optional = true
91+
pretty = true
92+
# Exclude virtual-env and build artefact directories so that `mypy .` from the
93+
# repo root matches CI behaviour (CI runs in a clean runner without a local venv).
94+
# Anchored regexes — unanchored `venv/` would match any path segment containing "venv/".
95+
exclude = ["^venv/", "^\\.venv/", "^build/", "^dist/"]

requirements.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1-
flask>=3.0
2-
fpdf2>=2.7
3-
pywebview>=5.0
1+
# Backward-compatibility shim — mirrors [project.dependencies] in pyproject.toml.
2+
# Keep version specifiers in sync when runtime deps change.
3+
#
4+
# Prefer: pip install -e . (installs the package + runtime deps)
5+
# pip install -e ".[dev]" (+ pytest and mypy)
6+
# pip install -e ".[desktop]" (+ pywebview for the GUI launcher)
7+
flask>=3.0,<4
8+
fpdf2>=2.7,<3
9+
pillow>=10.3.0
10+
# pywebview is desktop-only — install with: pip install -e ".[desktop]"

0 commit comments

Comments
 (0)