perfact-api-pd-fastapi 1.17__tar.gz → 1.18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/PKG-INFO +1 -1
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/grafana.py +8 -2
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact_api_pd_fastapi.egg-info/PKG-INFO +1 -1
- perfact_api_pd_fastapi-1.18/src/perfact_api_pd_fastapi.egg-info/scm_version.json +8 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_grafana.py +23 -0
- perfact_api_pd_fastapi-1.17/src/perfact_api_pd_fastapi.egg-info/scm_version.json +0 -8
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/README.md +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/pyproject.toml +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/setup.cfg +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/__init__.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/kpi.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/pdunit.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/pdunitlch.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/performancedata.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/py.typed +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact_api_pd_fastapi.egg-info/SOURCES.txt +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact_api_pd_fastapi.egg-info/dependency_links.txt +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact_api_pd_fastapi.egg-info/entry_points.txt +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact_api_pd_fastapi.egg-info/requires.txt +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact_api_pd_fastapi.egg-info/scm_file_list.json +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact_api_pd_fastapi.egg-info/top_level.txt +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/__init__.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/conftest.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/helpers.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/locustfile.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_init.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_kpi.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_lifecycle_lookup_wiring.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_pdunit.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_pdunitlch.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_performance.py +0 -0
- {perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tox.ini +0 -0
{perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/grafana.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Callable
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
-
from typing import Any, Sequence
|
|
3
|
+
from typing import Any, Literal, Sequence
|
|
4
4
|
|
|
5
5
|
from fastapi import HTTPException, status
|
|
6
6
|
from perfact.api.base import AuthInfo, VisibilityPolicy, VisibilityPolicyRegistry
|
|
@@ -120,7 +120,11 @@ class ToolDowntimePayload(BaseModel):
|
|
|
120
120
|
``top_n`` is bounded to [1, _TOOL_DOWNTIME_MAX_TOP_N]. The id filters and
|
|
121
121
|
``sort`` are normalized through the same tolerant parsing the raw handler
|
|
122
122
|
used, so an "All"/cleared template variable ('', [] or the unresolved
|
|
123
|
-
``$__all``) still means "no filter".
|
|
123
|
+
``$__all``) still means "no filter" / the default.
|
|
124
|
+
|
|
125
|
+
``sort_by`` picks the metric that ranks the top-N tools and orders the
|
|
126
|
+
output: ``"duration"`` (default, total downtime) or ``"quantity"``
|
|
127
|
+
(incident count). It is strict: any other value is rejected.
|
|
124
128
|
"""
|
|
125
129
|
|
|
126
130
|
model_config = ConfigDict(populate_by_name=True)
|
|
@@ -134,6 +138,7 @@ class ToolDowntimePayload(BaseModel):
|
|
|
134
138
|
pdtooltype_ids: list[int] = Field(default_factory=list, alias="pdtooltype")
|
|
135
139
|
pdtool_ids: list[int] = Field(default_factory=list, alias="pdtool")
|
|
136
140
|
sort: str = "desc"
|
|
141
|
+
sort_by: Literal["duration", "quantity"] = "duration"
|
|
137
142
|
|
|
138
143
|
@field_validator("plant_tssm_ids", "pdtooltype_ids", "pdtool_ids", mode="before")
|
|
139
144
|
@classmethod
|
|
@@ -194,6 +199,7 @@ def _tool_downtime_handler(
|
|
|
194
199
|
pdtooltype_ids=payload.pdtooltype_ids,
|
|
195
200
|
pdtool_ids=pdtool_ids,
|
|
196
201
|
sort=payload.sort,
|
|
202
|
+
sort_by=payload.sort_by,
|
|
197
203
|
)
|
|
198
204
|
return tool_downtime_grafana_resp(rows, target.refId)
|
|
199
205
|
|
|
@@ -242,6 +242,29 @@ def test_tool_downtime_handler_happy_path(monkeypatch: pytest.MonkeyPatch) -> No
|
|
|
242
242
|
assert captured["pdtool_ids"] == [5]
|
|
243
243
|
|
|
244
244
|
|
|
245
|
+
@pytest.mark.parametrize(
|
|
246
|
+
"payload, expected",
|
|
247
|
+
[
|
|
248
|
+
({"sort_by": "quantity"}, "quantity"),
|
|
249
|
+
({"sort_by": "duration"}, "duration"),
|
|
250
|
+
({}, "duration"), # absent -> default
|
|
251
|
+
],
|
|
252
|
+
)
|
|
253
|
+
def test_tool_downtime_payload_sort_by(payload, expected) -> None:
|
|
254
|
+
assert grafana.ToolDowntimePayload.model_validate(payload).sort_by == expected
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
@pytest.mark.parametrize("value", ["bogus", "", "QUANTITY", None, 1])
|
|
258
|
+
def test_tool_downtime_handler_rejects_invalid_sort_by(value) -> None:
|
|
259
|
+
target = Target(target="pd.kpi.tool_downtime", payload={"sort_by": value})
|
|
260
|
+
query = QueryRequest.model_validate({})
|
|
261
|
+
|
|
262
|
+
with pytest.raises(HTTPException) as exc:
|
|
263
|
+
grafana._tool_downtime_handler(Mock(), _auth(), Mock(), target, query)
|
|
264
|
+
|
|
265
|
+
assert exc.value.status_code == 400
|
|
266
|
+
|
|
267
|
+
|
|
245
268
|
def test_tool_downtime_handler_scopes_to_pdtool_visibility(
|
|
246
269
|
monkeypatch: pytest.MonkeyPatch,
|
|
247
270
|
) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/__init__.py
RENAMED
|
File without changes
|
{perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/kpi.py
RENAMED
|
File without changes
|
{perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/pdunit.py
RENAMED
|
File without changes
|
{perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/pdunitlch.py
RENAMED
|
File without changes
|
|
File without changes
|
{perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/src/perfact/api/pd_fastapi/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{perfact_api_pd_fastapi-1.17 → perfact_api_pd_fastapi-1.18}/tests/test_lifecycle_lookup_wiring.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|