Spaces:
Sleeping
Sleeping
Deploy PR search API contributor surface fallback
Browse files
src/slop_farmer/app/pr_search_api.py
CHANGED
|
@@ -152,8 +152,15 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 152 |
settings = request.app.state.settings
|
| 153 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 154 |
status = get_pr_search_status(settings.index_path, repo=repo_slug)
|
| 155 |
-
|
| 156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
|
| 158 |
@app.get("/v1/repos/{owner}/{repo}/pulls/{number}/similar")
|
| 159 |
async def pr_similar(
|
|
@@ -240,7 +247,10 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 240 |
) -> dict[str, Any]:
|
| 241 |
settings = request.app.state.settings
|
| 242 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 243 |
-
return get_issue_cluster_status(
|
|
|
|
|
|
|
|
|
|
| 244 |
|
| 245 |
@app.get("/v1/repos/{owner}/{repo}/issues/clusters")
|
| 246 |
async def issue_clusters(
|
|
@@ -253,7 +263,7 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 253 |
settings = request.app.state.settings
|
| 254 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 255 |
return list_issue_clusters(
|
| 256 |
-
|
| 257 |
limit=_limit(
|
| 258 |
limit,
|
| 259 |
default=settings.issue_list_limit_default,
|
|
@@ -273,7 +283,7 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 273 |
settings = request.app.state.settings
|
| 274 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 275 |
return get_issue_cluster(
|
| 276 |
-
|
| 277 |
cluster_id=cluster_id,
|
| 278 |
variant=variant,
|
| 279 |
)
|
|
@@ -289,7 +299,7 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 289 |
settings = request.app.state.settings
|
| 290 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 291 |
return get_issue_clusters_for_pr(
|
| 292 |
-
|
| 293 |
pr_number=number,
|
| 294 |
variant=variant,
|
| 295 |
)
|
|
@@ -306,7 +316,7 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 306 |
settings = request.app.state.settings
|
| 307 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 308 |
return check_issue_cluster_membership(
|
| 309 |
-
|
| 310 |
pr_number=number,
|
| 311 |
cluster_id=cluster_id,
|
| 312 |
variant=variant,
|
|
@@ -323,7 +333,7 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 323 |
settings = request.app.state.settings
|
| 324 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 325 |
return list_issue_duplicate_prs(
|
| 326 |
-
|
| 327 |
limit=_limit(
|
| 328 |
limit,
|
| 329 |
default=settings.issue_list_limit_default,
|
|
@@ -341,7 +351,10 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 341 |
) -> dict[str, Any]:
|
| 342 |
settings = request.app.state.settings
|
| 343 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 344 |
-
return get_issue_best(
|
|
|
|
|
|
|
|
|
|
| 345 |
|
| 346 |
@app.get("/v1/repos/{owner}/{repo}/contributors/status")
|
| 347 |
async def contributor_status(
|
|
@@ -351,7 +364,7 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 351 |
) -> dict[str, Any]:
|
| 352 |
settings = request.app.state.settings
|
| 353 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 354 |
-
return get_contributor_status(
|
| 355 |
|
| 356 |
@app.get("/v1/repos/{owner}/{repo}/contributors")
|
| 357 |
async def contributors(
|
|
@@ -363,7 +376,7 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 363 |
settings = request.app.state.settings
|
| 364 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 365 |
return list_contributors(
|
| 366 |
-
|
| 367 |
limit=_limit(
|
| 368 |
limit,
|
| 369 |
default=settings.contributor_list_limit_default,
|
|
@@ -380,7 +393,10 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 380 |
) -> dict[str, Any]:
|
| 381 |
settings = request.app.state.settings
|
| 382 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 383 |
-
return get_contributor(
|
|
|
|
|
|
|
|
|
|
| 384 |
|
| 385 |
@app.get("/v1/repos/{owner}/{repo}/contributors/{login}/risk")
|
| 386 |
async def contributor_risk(
|
|
@@ -391,7 +407,10 @@ def create_app(settings: PrSearchApiSettings | None = None) -> FastAPI:
|
|
| 391 |
) -> dict[str, Any]:
|
| 392 |
settings = request.app.state.settings
|
| 393 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 394 |
-
return get_contributor_risk(
|
|
|
|
|
|
|
|
|
|
| 395 |
|
| 396 |
return app
|
| 397 |
|
|
@@ -474,6 +493,23 @@ def _active_snapshot_dir(settings: PrSearchApiSettings, repo_slug: str) -> Path:
|
|
| 474 |
return _status_snapshot_dir(get_pr_search_status(settings.index_path, repo=repo_slug))
|
| 475 |
|
| 476 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 477 |
def _status_snapshot_dir(status: dict[str, Any]) -> Path:
|
| 478 |
snapshot_dir = status.get("snapshot_dir")
|
| 479 |
if not snapshot_dir:
|
|
@@ -481,6 +517,24 @@ def _status_snapshot_dir(status: dict[str, Any]) -> Path:
|
|
| 481 |
return Path(str(snapshot_dir))
|
| 482 |
|
| 483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
def _limit(value: int | None, *, default: int, maximum: int) -> int:
|
| 485 |
limit = default if value is None else value
|
| 486 |
if limit < 1:
|
|
|
|
| 152 |
settings = request.app.state.settings
|
| 153 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 154 |
status = get_pr_search_status(settings.index_path, repo=repo_slug)
|
| 155 |
+
issue_snapshot_dir = _surface_snapshot_dir(settings, repo_slug, surface="issues")
|
| 156 |
+
contributor_snapshot_dir = _surface_snapshot_dir(
|
| 157 |
+
settings, repo_slug, surface="contributors"
|
| 158 |
+
)
|
| 159 |
+
surface_payload = {
|
| 160 |
+
"issues": get_snapshot_surfaces(issue_snapshot_dir)["issues"],
|
| 161 |
+
"contributors": get_snapshot_surfaces(contributor_snapshot_dir)["contributors"],
|
| 162 |
+
}
|
| 163 |
+
return {**status, "surfaces": surface_payload}
|
| 164 |
|
| 165 |
@app.get("/v1/repos/{owner}/{repo}/pulls/{number}/similar")
|
| 166 |
async def pr_similar(
|
|
|
|
| 247 |
) -> dict[str, Any]:
|
| 248 |
settings = request.app.state.settings
|
| 249 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 250 |
+
return get_issue_cluster_status(
|
| 251 |
+
_surface_snapshot_dir(settings, repo_slug, surface="issues"),
|
| 252 |
+
variant=variant,
|
| 253 |
+
)
|
| 254 |
|
| 255 |
@app.get("/v1/repos/{owner}/{repo}/issues/clusters")
|
| 256 |
async def issue_clusters(
|
|
|
|
| 263 |
settings = request.app.state.settings
|
| 264 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 265 |
return list_issue_clusters(
|
| 266 |
+
_surface_snapshot_dir(settings, repo_slug, surface="issues"),
|
| 267 |
limit=_limit(
|
| 268 |
limit,
|
| 269 |
default=settings.issue_list_limit_default,
|
|
|
|
| 283 |
settings = request.app.state.settings
|
| 284 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 285 |
return get_issue_cluster(
|
| 286 |
+
_surface_snapshot_dir(settings, repo_slug, surface="issues"),
|
| 287 |
cluster_id=cluster_id,
|
| 288 |
variant=variant,
|
| 289 |
)
|
|
|
|
| 299 |
settings = request.app.state.settings
|
| 300 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 301 |
return get_issue_clusters_for_pr(
|
| 302 |
+
_surface_snapshot_dir(settings, repo_slug, surface="issues"),
|
| 303 |
pr_number=number,
|
| 304 |
variant=variant,
|
| 305 |
)
|
|
|
|
| 316 |
settings = request.app.state.settings
|
| 317 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 318 |
return check_issue_cluster_membership(
|
| 319 |
+
_surface_snapshot_dir(settings, repo_slug, surface="issues"),
|
| 320 |
pr_number=number,
|
| 321 |
cluster_id=cluster_id,
|
| 322 |
variant=variant,
|
|
|
|
| 333 |
settings = request.app.state.settings
|
| 334 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 335 |
return list_issue_duplicate_prs(
|
| 336 |
+
_surface_snapshot_dir(settings, repo_slug, surface="issues"),
|
| 337 |
limit=_limit(
|
| 338 |
limit,
|
| 339 |
default=settings.issue_list_limit_default,
|
|
|
|
| 351 |
) -> dict[str, Any]:
|
| 352 |
settings = request.app.state.settings
|
| 353 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 354 |
+
return get_issue_best(
|
| 355 |
+
_surface_snapshot_dir(settings, repo_slug, surface="issues"),
|
| 356 |
+
variant=variant,
|
| 357 |
+
)
|
| 358 |
|
| 359 |
@app.get("/v1/repos/{owner}/{repo}/contributors/status")
|
| 360 |
async def contributor_status(
|
|
|
|
| 364 |
) -> dict[str, Any]:
|
| 365 |
settings = request.app.state.settings
|
| 366 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 367 |
+
return get_contributor_status(_surface_snapshot_dir(settings, repo_slug, surface="contributors"))
|
| 368 |
|
| 369 |
@app.get("/v1/repos/{owner}/{repo}/contributors")
|
| 370 |
async def contributors(
|
|
|
|
| 376 |
settings = request.app.state.settings
|
| 377 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 378 |
return list_contributors(
|
| 379 |
+
_surface_snapshot_dir(settings, repo_slug, surface="contributors"),
|
| 380 |
limit=_limit(
|
| 381 |
limit,
|
| 382 |
default=settings.contributor_list_limit_default,
|
|
|
|
| 393 |
) -> dict[str, Any]:
|
| 394 |
settings = request.app.state.settings
|
| 395 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 396 |
+
return get_contributor(
|
| 397 |
+
_surface_snapshot_dir(settings, repo_slug, surface="contributors"),
|
| 398 |
+
author_login=login,
|
| 399 |
+
)
|
| 400 |
|
| 401 |
@app.get("/v1/repos/{owner}/{repo}/contributors/{login}/risk")
|
| 402 |
async def contributor_risk(
|
|
|
|
| 407 |
) -> dict[str, Any]:
|
| 408 |
settings = request.app.state.settings
|
| 409 |
repo_slug = _repo_slug(settings, owner, repo)
|
| 410 |
+
return get_contributor_risk(
|
| 411 |
+
_surface_snapshot_dir(settings, repo_slug, surface="contributors"),
|
| 412 |
+
author_login=login,
|
| 413 |
+
)
|
| 414 |
|
| 415 |
return app
|
| 416 |
|
|
|
|
| 493 |
return _status_snapshot_dir(get_pr_search_status(settings.index_path, repo=repo_slug))
|
| 494 |
|
| 495 |
|
| 496 |
+
def _surface_snapshot_dir(
|
| 497 |
+
settings: PrSearchApiSettings,
|
| 498 |
+
repo_slug: str,
|
| 499 |
+
*,
|
| 500 |
+
surface: Literal["issues", "contributors"],
|
| 501 |
+
) -> Path:
|
| 502 |
+
active_snapshot_dir = _active_snapshot_dir(settings, repo_slug)
|
| 503 |
+
if _surface_available(active_snapshot_dir, surface=surface):
|
| 504 |
+
return active_snapshot_dir
|
| 505 |
+
materialized_snapshot_dir = _materialized_snapshot_dir(settings)
|
| 506 |
+
if materialized_snapshot_dir is not None and _surface_available(
|
| 507 |
+
materialized_snapshot_dir, surface=surface
|
| 508 |
+
):
|
| 509 |
+
return materialized_snapshot_dir
|
| 510 |
+
return active_snapshot_dir
|
| 511 |
+
|
| 512 |
+
|
| 513 |
def _status_snapshot_dir(status: dict[str, Any]) -> Path:
|
| 514 |
snapshot_dir = status.get("snapshot_dir")
|
| 515 |
if not snapshot_dir:
|
|
|
|
| 517 |
return Path(str(snapshot_dir))
|
| 518 |
|
| 519 |
|
| 520 |
+
def _materialized_snapshot_dir(settings: PrSearchApiSettings) -> Path | None:
|
| 521 |
+
if settings.hf_repo_id is None:
|
| 522 |
+
return None
|
| 523 |
+
return settings.hf_materialize_dir or default_hf_materialize_dir(
|
| 524 |
+
settings.output_dir,
|
| 525 |
+
settings.hf_repo_id,
|
| 526 |
+
settings.hf_revision,
|
| 527 |
+
)
|
| 528 |
+
|
| 529 |
+
|
| 530 |
+
def _surface_available(snapshot_dir: Path, *, surface: Literal["issues", "contributors"]) -> bool:
|
| 531 |
+
if not snapshot_dir.exists():
|
| 532 |
+
return False
|
| 533 |
+
if surface == "issues":
|
| 534 |
+
return any(snapshot_dir.glob("analysis-report*.json"))
|
| 535 |
+
return (snapshot_dir / "new-contributors-report.json").exists()
|
| 536 |
+
|
| 537 |
+
|
| 538 |
def _limit(value: int | None, *, default: int, maximum: int) -> int:
|
| 539 |
limit = default if value is None else value
|
| 540 |
if limit < 1:
|