Coverage for /usr/local/lib/python3.12/site-packages/prefect/server/events/jinja_filters.py: 31%
40 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 02:04 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 02:04 +0000
1from __future__ import annotations
3import re
4import urllib.parse
5from typing import Any, Callable, Mapping
7from jinja2 import pass_context
9from prefect.server.schemas.core import (
10 Deployment,
11 Flow,
12 FlowRun,
13 TaskRun,
14 WorkPool,
15 WorkQueue,
16)
17from prefect.server.schemas.responses import WorkQueueWithStatus
18from prefect.server.utilities.schemas import ORMBaseModel
19from prefect.settings import PREFECT_UI_URL
20from prefect.utilities.urls import url_for
22model_to_kind: dict[type[ORMBaseModel], str] = {
23 Deployment: "prefect.deployment",
24 Flow: "prefect.flow",
25 FlowRun: "prefect.flow-run",
26 TaskRun: "prefect.task-run",
27 WorkQueue: "prefect.work-queue",
28 WorkQueueWithStatus: "prefect.work-queue",
29 WorkPool: "prefect.work-pool",
30}
33@pass_context
34def ui_url(ctx: Mapping[str, Any], obj: Any) -> str | None:
35 """Return the UI URL for the given object."""
36 return url_for(obj, url_type="ui")
39@pass_context
40def ui_resource_events_url(ctx: Mapping[str, Any], obj: Any) -> str | None:
41 """Given a Resource or Model, return a UI link to the events page
42 filtered for that resource. If an unsupported object is provided,
43 return `None`.
45 Currently supports Automation, Resource, Deployment, Flow, FlowRun, TaskRun, and
46 WorkQueue objects. Within a Resource, deployment, flow, flow-run, task-run,
47 and work-queue are supported."""
48 from prefect.server.events.schemas.automations import Automation
49 from prefect.server.events.schemas.events import Resource
51 url = None
52 url_format = "events?resource={resource_id}"
54 if isinstance(obj, Automation):
55 url = url_format.format(resource_id=f"prefect.automation.{obj.id}")
56 elif isinstance(obj, Resource):
57 kind, _, id = obj.id.rpartition(".")
58 url = url_format.format(resource_id=f"{kind}.{id}")
59 elif isinstance(obj, ORMBaseModel):
60 kind = model_to_kind.get(type(obj)) # type: ignore
62 if kind:
63 url = url_format.format(resource_id=f"{kind}.{obj.id}")
64 if url:
65 return urllib.parse.urljoin(PREFECT_UI_URL.value(), url)
66 else:
67 return None
70def flow_run_id(text: str | None) -> str | None:
71 """Extract a flow run ID from a string, such as a PR body."""
72 if not text:
73 return None
74 match = re.search(
75 r"flow-run/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
76 text,
77 )
78 if match:
79 return match.group(1)
80 return None
83all_filters: dict[str, Callable[[Mapping[str, Any], Any], str | None]] = {
84 "ui_url": ui_url,
85 "ui_resource_events_url": ui_resource_events_url,
86 "flow_run_id": flow_run_id, # type: ignore
87}