Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
476014b
Add Facility API, demo data, stricter query validation and /api/v1 di…
juztas Jan 12, 2026
9985b7d
Make NamedObject reusable
juztas Jan 15, 2026
bf82bcc
Include operation_id for facility (similar to pull request #21)
juztas Jan 15, 2026
75945e0
simplified facility endpoint proposal
gabor-lbl Jan 15, 2026
52567f2
Add Facility API, demo data, stricter query validation and /api/v1 di…
juztas Jan 12, 2026
0dbb6d8
Remove /api/v1
juztas Jan 15, 2026
65a4e46
Refactor shared validators & models to fix import loading issues
juztas Jan 20, 2026
f4adcb6
Github Action to validate api
juztas Jan 20, 2026
b3e96f7
Add custom get extra function
juztas Jan 20, 2026
5b4d7e2
Implement opentelemetry. Use UTC in demo adapter
juztas Jan 20, 2026
b697d18
Rename dependencies to common
juztas Jan 20, 2026
db5878c
Do not swallow exceptions
juztas Jan 21, 2026
df38b39
Ensure that computed fields are included in output
juztas Jan 22, 2026
a634c63
Code base compliant with the official Spec
juztas Jan 23, 2026
bca4945
Fully compliant with official spec
juztas Jan 23, 2026
a6bc9af
Enforce Py 3.14 as used release for everything
juztas Jan 23, 2026
8d830e0
Enable deepsource scanning
juztas Jan 23, 2026
f4914e8
Enforce consistent package versions (pin major/minor version)
juztas Jan 25, 2026
cba88c2
Add Facility API, demo data, stricter query validation and /api/v1 di…
juztas Jan 12, 2026
6f44f67
Make NamedObject reusable
juztas Jan 15, 2026
fbab525
Include operation_id for facility (similar to pull request #21)
juztas Jan 15, 2026
7ca9b75
simplified facility endpoint proposal
gabor-lbl Jan 15, 2026
936cf35
Add Facility API, demo data, stricter query validation and /api/v1 di…
juztas Jan 12, 2026
58d5602
Remove /api/v1
juztas Jan 15, 2026
630cd61
Refactor shared validators & models to fix import loading issues
juztas Jan 20, 2026
2cf089b
Github Action to validate api
juztas Jan 20, 2026
ea013e2
Add custom get extra function
juztas Jan 20, 2026
9eb22d9
Implement opentelemetry. Use UTC in demo adapter
juztas Jan 20, 2026
a23407e
Rename dependencies to common
juztas Jan 20, 2026
85c8e76
Do not swallow exceptions
juztas Jan 21, 2026
29b6ff0
Ensure that computed fields are included in output
juztas Jan 22, 2026
94094de
Code base compliant with the official Spec
juztas Jan 23, 2026
9c2eb9e
Fully compliant with official spec
juztas Jan 23, 2026
2bd894c
Enforce Py 3.14 as used release for everything
juztas Jan 23, 2026
21c03ca
Enable deepsource scanning
juztas Jan 23, 2026
6cb85bf
Enforce consistent package versions (pin major/minor version)
juztas Jan 25, 2026
6ccddc7
Make adapter forward compatible. add filtering, pagination, datetime …
juztas Feb 3, 2026
ccfd2fe
Remove kwargs (versioning agreed)
juztas Feb 4, 2026
1206be9
get_resource single id
juztas Feb 4, 2026
1c78ca6
Merge branch 'main' into kwargslint
juztas Feb 4, 2026
ac96466
Merge branch 'main' into kwargslint
juztas Feb 5, 2026
b141dbd
Add paginate in demo_adapter. Fix number of params for override method
juztas Feb 5, 2026
ef5c6e2
Harden validation and response allingment with spec
juztas Feb 5, 2026
f9ee205
Merge branch 'main' into kwargslint
juztas Feb 6, 2026
3273b8a
Add site_id under resource. Fix schemathesis run with excluding none …
juztas Feb 7, 2026
68a72bc
Split common.py into it's own types
juztas Feb 7, 2026
41b3400
Merge pull request #1 from juztas/kwargslint
juztas Feb 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 115 additions & 82 deletions app/demo_adapter.py

Large diffs are not rendered by default.

51 changes: 26 additions & 25 deletions app/routers/account/account.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from fastapi import HTTPException, Request, Depends, Query
from . import models, facility_adapter
from fastapi import Depends, HTTPException, Query, Request

from ...types.http import forbidExtraQueryParams
from ...types.models import Capability
from ...types.scalars import StrictDateTime
from .. import iri_router
from ..error_handlers import DEFAULT_RESPONSES
from ..common import forbidExtraQueryParams, StrictDateTime, Capability

from . import facility_adapter, models

router = iri_router.IriRouter(
facility_adapter.FacilityAdapter,
Expand All @@ -18,8 +20,7 @@
description="Get a list of capabilities at this facility.",
responses=DEFAULT_RESPONSES,
operation_id="getCapabilities",

)
response_model_exclude_none=True)
async def get_capabilities(
request : Request,
name : str = Query(default=None, min_length=1),
Expand All @@ -28,7 +29,7 @@ async def get_capabilities(
limit : int = Query(default=100, ge=0, le=1000),
_forbid = Depends(forbidExtraQueryParams("name", "modified_since", "offset", "limit")),
) -> list[Capability]:
return await router.adapter.get_capabilities()
return await router.adapter.get_capabilities(name=name, modified_since=modified_since, offset=offset, limit=limit)


@router.get(
Expand All @@ -44,7 +45,7 @@ async def get_capability(
modified_since: StrictDateTime = Query(default=None),
_forbid = Depends(forbidExtraQueryParams("modified_since")),
) -> Capability:
caps = await router.adapter.get_capabilities()
caps = await router.adapter.get_capabilities(name=None, modified_since=modified_since, offset=0, limit=100)
cc = next((c for c in caps if c.id == capability_id), None)
if not cc:
raise HTTPException(status_code=404, detail="Capability not found")
Expand All @@ -63,7 +64,7 @@ async def get_projects(
request : Request,
_forbid = Depends(forbidExtraQueryParams()),
) -> list[models.Project]:
user = await router.adapter.get_user(request.state.current_user_id, request.state.api_key, iri_router.get_client_ip(request))
user = await router.adapter.get_user(user_id=request.state.current_user_id, api_key=request.state.api_key, client_ip=iri_router.get_client_ip(request))
if not user:
raise HTTPException(status_code=404, detail="User not found")
return await router.adapter.get_projects(user)
Expand All @@ -82,10 +83,10 @@ async def get_project(
request : Request,
_forbid = Depends(forbidExtraQueryParams()),
) -> models.Project:
user = await router.adapter.get_user(request.state.current_user_id, request.state.api_key, iri_router.get_client_ip(request))
user = await router.adapter.get_user(user_id=request.state.current_user_id, api_key=request.state.api_key, client_ip=iri_router.get_client_ip(request))
if not user:
raise HTTPException(status_code=404, detail="User not found")
projects = await router.adapter.get_projects(user)
projects = await router.adapter.get_projects(user=user)
pp = next((p for p in projects if p.id == project_id), None)
if not pp:
raise HTTPException(status_code=404, detail="Project not found")
Expand All @@ -105,14 +106,14 @@ async def get_project_allocations(
request : Request,
_forbid = Depends(forbidExtraQueryParams()),
) -> list[models.ProjectAllocation]:
user = await router.adapter.get_user(request.state.current_user_id, request.state.api_key, iri_router.get_client_ip(request))
user = await router.adapter.get_user(user_id=request.state.current_user_id, api_key=request.state.api_key, client_ip=iri_router.get_client_ip(request))
if not user:
raise HTTPException(status_code=404, detail="User not found")
projects = await router.adapter.get_projects(user)
projects = await router.adapter.get_projects(user=user)
project = next((p for p in projects if p.id == project_id), None)
if not project:
raise HTTPException(status_code=404, detail="Project not found")
return await router.adapter.get_project_allocations(project, user)
return await router.adapter.get_project_allocations(project=project, user=user)


@router.get(
Expand All @@ -129,12 +130,12 @@ async def get_project_allocation(
request : Request,
_forbid = Depends(forbidExtraQueryParams()),
) -> models.ProjectAllocation:
user = await router.adapter.get_user(request.state.current_user_id, request.state.api_key, iri_router.get_client_ip(request))
user = await router.adapter.get_user(user_id=request.state.current_user_id, api_key=request.state.api_key, client_ip=iri_router.get_client_ip(request))
if not user:
raise HTTPException(status_code=404, detail="User not found")
projects = await router.adapter.get_projects(user)
projects = await router.adapter.get_projects(user=user)
project = next((p for p in projects if p.id == project_id), None)
pas = await router.adapter.get_project_allocations(project, user)
pas = await router.adapter.get_project_allocations(project=project, user=user)
pa = next((pa for pa in pas if pa.id == project_allocation_id), None)
if not pa:
raise HTTPException(status_code=404, detail="Project allocation not found")
Expand All @@ -155,18 +156,18 @@ async def get_user_allocations(
request : Request,
_forbid = Depends(forbidExtraQueryParams()),
) -> list[models.UserAllocation]:
user = await router.adapter.get_user(request.state.current_user_id, request.state.api_key, iri_router.get_client_ip(request))
user = await router.adapter.get_user(user_id=request.state.current_user_id, api_key=request.state.api_key, client_ip=iri_router.get_client_ip(request))
if not user:
raise HTTPException(status_code=404, detail="User not found")
projects = await router.adapter.get_projects(user)
projects = await router.adapter.get_projects(user=user)
project = next((p for p in projects if p.id == project_id), None)
if not project:
raise HTTPException(status_code=404, detail="Project not found")
pas = await router.adapter.get_project_allocations(project, user)
pas = await router.adapter.get_project_allocations(project=project, user=user)
pa = next((pa for pa in pas if pa.id == project_allocation_id), None)
if not pa:
raise HTTPException(status_code=404, detail="Project allocation not found")
return await router.adapter.get_user_allocations(user, pa)
return await router.adapter.get_user_allocations(user=user, project_allocation=pa)


@router.get(
Expand All @@ -184,18 +185,18 @@ async def get_user_allocation(
request : Request,
_forbid = Depends(forbidExtraQueryParams()),
) -> models.UserAllocation:
user = await router.adapter.get_user(request.state.current_user_id, request.state.api_key, iri_router.get_client_ip(request))
user = await router.adapter.get_user(user_id=request.state.current_user_id, api_key=request.state.api_key, client_ip=iri_router.get_client_ip(request))
if not user:
raise HTTPException(status_code=404, detail="User not found")
projects = await router.adapter.get_projects(user)
projects = await router.adapter.get_projects(user=user)
project = next((p for p in projects if p.id == project_id), None)
if not project:
raise HTTPException(status_code=404, detail="Project not found")
pas = await router.adapter.get_project_allocations(project, user)
pas = await router.adapter.get_project_allocations(project=project, user=user)
pa = next((pa for pa in pas if pa.id == project_allocation_id), None)
if not pa:
raise HTTPException(status_code=404, detail="Project allocation not found")
uas = await router.adapter.get_user_allocations(user, pa)
uas = await router.adapter.get_user_allocations(user=user, project_allocation=pa)
ua = next((ua for ua in uas if ua.id == user_allocation_id), None)
if not ua:
raise HTTPException(status_code=404, detail="User allocation not found")
Expand Down
11 changes: 8 additions & 3 deletions app/routers/account/facility_adapter.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from abc import abstractmethod
from . import models as account_models
from ..common import Capability

from ...types.models import Capability
from ..iri_router import AuthenticatedAdapter
from . import models as account_models


class FacilityAdapter(AuthenticatedAdapter):
Expand All @@ -14,6 +15,10 @@ class FacilityAdapter(AuthenticatedAdapter):
@abstractmethod
async def get_capabilities(
self : "FacilityAdapter",
name : str | None = None,
modified_since : str | None = None,
offset : int = 0,
limit : int = 1000
) -> list[Capability]:
pass

Expand All @@ -39,6 +44,6 @@ async def get_project_allocations(
async def get_user_allocations(
self : "FacilityAdapter",
user: account_models.User,
project_allocation: account_models.ProjectAllocation,
project_allocation: account_models.ProjectAllocation
) -> list[account_models.UserAllocation]:
pass
6 changes: 4 additions & 2 deletions app/routers/account/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from pydantic import computed_field, Field
from pydantic import Field, computed_field

from ... import config
from ..common import IRIBaseModel, AllocationUnit
from ...types.base import IRIBaseModel
from ...types.scalars import AllocationUnit


class User(IRIBaseModel):
Expand Down
204 changes: 0 additions & 204 deletions app/routers/common.py

This file was deleted.

Loading