perfact-api-pd-fastapi 1.16__tar.gz → 1.17__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.16 → perfact_api_pd_fastapi-1.17}/PKG-INFO +2 -1
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/pyproject.toml +1 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/pdunit.py +9 -4
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/pdunitlch.py +34 -36
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact_api_pd_fastapi.egg-info/PKG-INFO +2 -1
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact_api_pd_fastapi.egg-info/SOURCES.txt +1 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact_api_pd_fastapi.egg-info/requires.txt +1 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact_api_pd_fastapi.egg-info/scm_file_list.json +1 -0
- perfact_api_pd_fastapi-1.17/src/perfact_api_pd_fastapi.egg-info/scm_version.json +8 -0
- perfact_api_pd_fastapi-1.17/tests/conftest.py +58 -0
- perfact_api_pd_fastapi-1.17/tests/test_lifecycle_lookup_wiring.py +14 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/test_pdunit.py +6 -1
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/test_pdunitlch.py +4 -0
- perfact_api_pd_fastapi-1.16/src/perfact_api_pd_fastapi.egg-info/scm_version.json +0 -8
- perfact_api_pd_fastapi-1.16/tests/conftest.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/README.md +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/setup.cfg +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/__init__.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/grafana.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/kpi.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/performancedata.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/py.typed +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact_api_pd_fastapi.egg-info/dependency_links.txt +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact_api_pd_fastapi.egg-info/entry_points.txt +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact_api_pd_fastapi.egg-info/top_level.txt +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/__init__.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/helpers.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/locustfile.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/test_grafana.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/test_init.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/test_kpi.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tests/test_performance.py +0 -0
- {perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: perfact-api-pd-fastapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17
|
|
4
4
|
Summary: PerFact API - SQLAlchemy+FastAPI pd apis package
|
|
5
5
|
Author-email: Viktor Dick <viktor.dick@perfact.de>
|
|
6
6
|
License-Expression: GPL-2.0-or-later
|
|
@@ -14,6 +14,7 @@ Requires-Dist: perfact-api-pp
|
|
|
14
14
|
Requires-Dist: perfact-api-pd
|
|
15
15
|
Requires-Dist: perfact-api-main
|
|
16
16
|
Requires-Dist: perfact-api-it
|
|
17
|
+
Requires-Dist: perfact-api-i18n-fastapi
|
|
17
18
|
|
|
18
19
|
# PerFact API - pd - APIs
|
|
19
20
|
|
{perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/pdunit.py
RENAMED
|
@@ -2,10 +2,11 @@ from typing import Optional, Sequence
|
|
|
2
2
|
|
|
3
3
|
from fastapi import HTTPException
|
|
4
4
|
from perfact.api.base.model import PydanticBase
|
|
5
|
+
from perfact.api.i18n_fastapi import Lang
|
|
5
6
|
from perfact.api.main import Auth, DBSession, VisibilityRegistryDep, require_roles
|
|
6
7
|
from perfact.api.main.dbsession import APIRouter
|
|
7
8
|
from perfact.api.pd.model import PdUnit
|
|
8
|
-
from
|
|
9
|
+
from perfact.api.pd.services import list_pdunits
|
|
9
10
|
|
|
10
11
|
routes = APIRouter()
|
|
11
12
|
|
|
@@ -26,8 +27,11 @@ class PdUnitGet(PydanticBase):
|
|
|
26
27
|
)
|
|
27
28
|
@require_roles("PdRead")
|
|
28
29
|
def pdunit_get_all(
|
|
29
|
-
session: DBSession,
|
|
30
|
-
|
|
30
|
+
session: DBSession,
|
|
31
|
+
auth: Auth,
|
|
32
|
+
visibility: VisibilityRegistryDep,
|
|
33
|
+
lang: Lang,
|
|
34
|
+
) -> Sequence[PdUnitGet]:
|
|
31
35
|
"""
|
|
32
36
|
returns all PdUnit which the current user is allowed to see.
|
|
33
37
|
"""
|
|
@@ -35,7 +39,8 @@ def pdunit_get_all(
|
|
|
35
39
|
if auth is None:
|
|
36
40
|
raise HTTPException(status_code=401, detail="Not authenticated")
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
rows = list_pdunits(session, lang, policy.filter(auth))
|
|
43
|
+
return [PdUnitGet.model_validate(row) for row in rows]
|
|
39
44
|
|
|
40
45
|
|
|
41
46
|
def mount(app: APIRouter):
|
{perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/pdunitlch.py
RENAMED
|
@@ -3,17 +3,19 @@ from typing import Optional, Sequence
|
|
|
3
3
|
|
|
4
4
|
from fastapi import HTTPException, Query
|
|
5
5
|
from perfact.api.base.model import PydanticBase
|
|
6
|
+
from perfact.api.i18n_fastapi import Lang
|
|
6
7
|
from perfact.api.main import Auth, DBSession, VisibilityRegistryDep, require_roles
|
|
7
8
|
from perfact.api.main.dbsession import APIRouter
|
|
8
|
-
from perfact.api.pd.model import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
from perfact.api.pd.model import PdOrdLch, PdUnit, PdUnitLct
|
|
10
|
+
from perfact.api.pd.services import (
|
|
11
|
+
find_pdunit,
|
|
12
|
+
get_unit_lch_history,
|
|
13
|
+
list_pdordlc,
|
|
14
|
+
list_pdordlch,
|
|
15
|
+
list_pdordlct,
|
|
16
|
+
list_pdunitlc,
|
|
17
|
+
list_pdunitlct,
|
|
15
18
|
)
|
|
16
|
-
from perfact.api.pd.services.pdunitlch import UnitLchHistoryEntry, get_unit_lch_history
|
|
17
19
|
from pydantic import BaseModel, ConfigDict
|
|
18
20
|
from sqlalchemy import select
|
|
19
21
|
|
|
@@ -72,8 +74,10 @@ class PdUnitLchEntryGet(BaseModel):
|
|
|
72
74
|
response_model=Sequence[PdUnitLcGet],
|
|
73
75
|
)
|
|
74
76
|
@require_roles("PdRead")
|
|
75
|
-
def pdunitlc_get_all(
|
|
76
|
-
|
|
77
|
+
def pdunitlc_get_all(
|
|
78
|
+
session: DBSession, auth: Auth, lang: Lang
|
|
79
|
+
) -> Sequence[PdUnitLcGet]:
|
|
80
|
+
return [PdUnitLcGet.model_validate(row) for row in list_pdunitlc(session, lang)]
|
|
77
81
|
|
|
78
82
|
|
|
79
83
|
@routes.get(
|
|
@@ -84,7 +88,7 @@ def pdunitlc_get_all(session: DBSession, auth: Auth) -> Sequence[PdUnitLc]:
|
|
|
84
88
|
)
|
|
85
89
|
@require_roles("PdRead")
|
|
86
90
|
def pdunitlct_get_all(session: DBSession, auth: Auth) -> Sequence[PdUnitLct]:
|
|
87
|
-
return session
|
|
91
|
+
return list_pdunitlct(session)
|
|
88
92
|
|
|
89
93
|
|
|
90
94
|
@routes.get(
|
|
@@ -94,8 +98,8 @@ def pdunitlct_get_all(session: DBSession, auth: Auth) -> Sequence[PdUnitLct]:
|
|
|
94
98
|
response_model=Sequence[PdOrdLcGet],
|
|
95
99
|
)
|
|
96
100
|
@require_roles("PdRead")
|
|
97
|
-
def pdordlc_get_all(session: DBSession, auth: Auth) -> Sequence[
|
|
98
|
-
return
|
|
101
|
+
def pdordlc_get_all(session: DBSession, auth: Auth, lang: Lang) -> Sequence[PdOrdLcGet]:
|
|
102
|
+
return [PdOrdLcGet.model_validate(row) for row in list_pdordlc(session, lang)]
|
|
99
103
|
|
|
100
104
|
|
|
101
105
|
@routes.get(
|
|
@@ -105,8 +109,10 @@ def pdordlc_get_all(session: DBSession, auth: Auth) -> Sequence[PdOrdLc]:
|
|
|
105
109
|
response_model=Sequence[PdOrdLctGet],
|
|
106
110
|
)
|
|
107
111
|
@require_roles("PdRead")
|
|
108
|
-
def pdordlct_get_all(
|
|
109
|
-
|
|
112
|
+
def pdordlct_get_all(
|
|
113
|
+
session: DBSession, auth: Auth, lang: Lang
|
|
114
|
+
) -> Sequence[PdOrdLctGet]:
|
|
115
|
+
return [PdOrdLctGet.model_validate(row) for row in list_pdordlct(session, lang)]
|
|
110
116
|
|
|
111
117
|
|
|
112
118
|
@routes.get(
|
|
@@ -117,7 +123,7 @@ def pdordlct_get_all(session: DBSession, auth: Auth) -> Sequence[PdOrdLct]:
|
|
|
117
123
|
)
|
|
118
124
|
@require_roles("PdRead")
|
|
119
125
|
def pdordlch_get_all(session: DBSession, auth: Auth) -> Sequence[PdOrdLch]:
|
|
120
|
-
return session
|
|
126
|
+
return list_pdordlch(session)
|
|
121
127
|
|
|
122
128
|
|
|
123
129
|
@routes.get(
|
|
@@ -130,30 +136,21 @@ def pdordlch_get_all(session: DBSession, auth: Auth) -> Sequence[PdOrdLch]:
|
|
|
130
136
|
def pdunitlch_get(
|
|
131
137
|
session: DBSession,
|
|
132
138
|
auth: Auth,
|
|
139
|
+
lang: Lang,
|
|
133
140
|
visibility: VisibilityRegistryDep,
|
|
134
141
|
pdunit_id: Optional[int] = None,
|
|
135
142
|
pdunit_num: Optional[str] = None,
|
|
136
143
|
sample_count: Optional[int] = Query(default=None, ge=1, le=MAX_SAMPLE_COUNT),
|
|
137
144
|
starttime: Optional[datetime.datetime] = None,
|
|
138
145
|
endtime: Optional[datetime.datetime] = None,
|
|
139
|
-
) -> list[
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
).scalar_one_or_none()
|
|
147
|
-
else:
|
|
148
|
-
raise HTTPException(status_code=422, detail="Provide pdunit_id or pdunit_num")
|
|
149
|
-
|
|
150
|
-
if unit is None:
|
|
151
|
-
raise HTTPException(
|
|
152
|
-
status_code=404,
|
|
153
|
-
detail=f"PdUnit not found: {pdunit_id or pdunit_num!r}",
|
|
154
|
-
)
|
|
146
|
+
) -> list[PdUnitLchEntryGet]:
|
|
147
|
+
try:
|
|
148
|
+
unit = find_pdunit(session, pdunit_id=pdunit_id, pdunit_num=pdunit_num)
|
|
149
|
+
except ValueError as exc:
|
|
150
|
+
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
|
151
|
+
except LookupError as exc:
|
|
152
|
+
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
155
153
|
|
|
156
|
-
# Visibility check applies regardless of which lookup path was used
|
|
157
154
|
try:
|
|
158
155
|
policy = visibility.get(PdUnit)
|
|
159
156
|
except KeyError:
|
|
@@ -167,17 +164,18 @@ def pdunitlch_get(
|
|
|
167
164
|
raise HTTPException(status_code=404)
|
|
168
165
|
|
|
169
166
|
try:
|
|
170
|
-
|
|
167
|
+
history = get_unit_lch_history(
|
|
171
168
|
session,
|
|
172
169
|
pdunit_id=unit.id,
|
|
173
170
|
starttime=starttime,
|
|
174
171
|
endtime=endtime,
|
|
175
172
|
sample_count=sample_count,
|
|
173
|
+
lang=lang,
|
|
176
174
|
)
|
|
177
175
|
except ValueError as exc:
|
|
178
176
|
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
|
|
178
|
+
return [PdUnitLchEntryGet.model_validate(entry) for entry in history]
|
|
181
179
|
|
|
182
180
|
|
|
183
181
|
def mount(app: APIRouter) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: perfact-api-pd-fastapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17
|
|
4
4
|
Summary: PerFact API - SQLAlchemy+FastAPI pd apis package
|
|
5
5
|
Author-email: Viktor Dick <viktor.dick@perfact.de>
|
|
6
6
|
License-Expression: GPL-2.0-or-later
|
|
@@ -14,6 +14,7 @@ Requires-Dist: perfact-api-pp
|
|
|
14
14
|
Requires-Dist: perfact-api-pd
|
|
15
15
|
Requires-Dist: perfact-api-main
|
|
16
16
|
Requires-Dist: perfact-api-it
|
|
17
|
+
Requires-Dist: perfact-api-i18n-fastapi
|
|
17
18
|
|
|
18
19
|
# PerFact API - pd - APIs
|
|
19
20
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from perfact.api.base.model import Base
|
|
3
|
+
from perfact.api.i18n.model import I18nLang
|
|
4
|
+
from perfact.api.pd.model import (
|
|
5
|
+
PdOrdLc,
|
|
6
|
+
PdOrdLcI18n,
|
|
7
|
+
PdOrdLct,
|
|
8
|
+
PdOrdLctI18n,
|
|
9
|
+
PdPlant,
|
|
10
|
+
PdUnit,
|
|
11
|
+
PdUnitGroup,
|
|
12
|
+
PdUnitI18n,
|
|
13
|
+
PdUnitLc,
|
|
14
|
+
PdUnitLcI18n,
|
|
15
|
+
)
|
|
16
|
+
from pytest_postgresql import factories
|
|
17
|
+
from sqlalchemy import create_engine, text
|
|
18
|
+
from sqlalchemy.orm import Session
|
|
19
|
+
|
|
20
|
+
postgresql_proc = factories.postgresql_proc()
|
|
21
|
+
postgresql = factories.postgresql("postgresql_proc")
|
|
22
|
+
|
|
23
|
+
_TABLES = [
|
|
24
|
+
I18nLang.__table__,
|
|
25
|
+
PdUnitLc.__table__,
|
|
26
|
+
PdUnitLcI18n.__table__,
|
|
27
|
+
PdOrdLc.__table__,
|
|
28
|
+
PdOrdLcI18n.__table__,
|
|
29
|
+
PdOrdLct.__table__,
|
|
30
|
+
PdOrdLctI18n.__table__,
|
|
31
|
+
PdPlant.__table__,
|
|
32
|
+
PdUnitGroup.__table__,
|
|
33
|
+
PdUnit.__table__,
|
|
34
|
+
PdUnitI18n.__table__,
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.fixture
|
|
39
|
+
def db_engine(postgresql):
|
|
40
|
+
info = postgresql.info
|
|
41
|
+
url = f"postgresql+psycopg://{info.user}@{info.host}:{info.port}/{info.dbname}"
|
|
42
|
+
engine = create_engine(url)
|
|
43
|
+
with engine.begin() as conn:
|
|
44
|
+
conn.execute(
|
|
45
|
+
text(
|
|
46
|
+
"CREATE OR REPLACE FUNCTION db_username() RETURNS text "
|
|
47
|
+
"LANGUAGE SQL AS 'SELECT current_user'"
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
Base.metadata.create_all(engine, tables=_TABLES)
|
|
51
|
+
yield engine
|
|
52
|
+
engine.dispose()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@pytest.fixture
|
|
56
|
+
def db_session(db_engine):
|
|
57
|
+
with Session(db_engine) as session:
|
|
58
|
+
yield session
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from perfact.api.main.dbsession import APIRouter
|
|
2
|
+
from perfact.api.pd_fastapi import pdunitlch
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_mount_includes_pdunitlc_pdordlc_pdordlct_routes() -> None:
|
|
6
|
+
"""Mounting registers the lifecycle lookup routes."""
|
|
7
|
+
from .helpers import collect_paths
|
|
8
|
+
|
|
9
|
+
app_router = APIRouter()
|
|
10
|
+
|
|
11
|
+
pdunitlch.mount(app_router)
|
|
12
|
+
|
|
13
|
+
paths = collect_paths(app_router)
|
|
14
|
+
assert {"/pdunitlc", "/pdordlc", "/pdordlct"} <= paths
|
|
@@ -36,7 +36,12 @@ def test_pdunit_get_all_requires_authentication() -> None:
|
|
|
36
36
|
|
|
37
37
|
with pytest.raises(HTTPException, match="Not authenticated") as exc_info:
|
|
38
38
|
asyncio.run(
|
|
39
|
-
pdunit.pdunit_get_all(
|
|
39
|
+
pdunit.pdunit_get_all(
|
|
40
|
+
session=session,
|
|
41
|
+
auth=None, # type: ignore[arg-type]
|
|
42
|
+
visibility=visibility, # type: ignore[arg-type]
|
|
43
|
+
lang=None,
|
|
44
|
+
)
|
|
40
45
|
)
|
|
41
46
|
|
|
42
47
|
assert exc_info.value.status_code == 401
|
|
@@ -41,8 +41,10 @@ def test_pdunitlchentryget_exposes_pdordlc_name() -> None:
|
|
|
41
41
|
entry = UnitLchHistoryEntry(
|
|
42
42
|
createtime=datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc),
|
|
43
43
|
pdunitlct_name="start",
|
|
44
|
+
pdunitlc_id=1,
|
|
44
45
|
pdunitlc_name="running",
|
|
45
46
|
pdord_num="ORD-1",
|
|
47
|
+
pdordlc_id=2,
|
|
46
48
|
pdordlc_name="active",
|
|
47
49
|
)
|
|
48
50
|
|
|
@@ -55,8 +57,10 @@ def test_pdunitlchentryget_pdordlc_name_none_when_no_active_operation() -> None:
|
|
|
55
57
|
entry = UnitLchHistoryEntry(
|
|
56
58
|
createtime=datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc),
|
|
57
59
|
pdunitlct_name="start",
|
|
60
|
+
pdunitlc_id=1,
|
|
58
61
|
pdunitlc_name="running",
|
|
59
62
|
pdord_num=None,
|
|
63
|
+
pdordlc_id=None,
|
|
60
64
|
pdordlc_name=None,
|
|
61
65
|
)
|
|
62
66
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/__init__.py
RENAMED
|
File without changes
|
{perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/grafana.py
RENAMED
|
File without changes
|
{perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/src/perfact/api/pd_fastapi/kpi.py
RENAMED
|
File without changes
|
|
File without changes
|
{perfact_api_pd_fastapi-1.16 → perfact_api_pd_fastapi-1.17}/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
|