xcpcio 0.63.6__py3-none-any.whl → 0.63.7__py3-none-any.whl

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.

Potentially problematic release.


This version of xcpcio might be problematic. Click here for more details.

xcpcio/__version__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # This file is auto-generated by Hatchling. As such, do not:
2
2
  # - modify
3
3
  # - track in version control e.g. be sure to add to .gitignore
4
- __version__ = VERSION = '0.63.6'
4
+ __version__ = VERSION = '0.63.7'
@@ -8,6 +8,7 @@ from fastapi import APIRouter
8
8
 
9
9
  from . import (
10
10
  access,
11
+ accounts,
11
12
  awards,
12
13
  clarifications,
13
14
  contests,
@@ -30,6 +31,7 @@ def create_router() -> APIRouter:
30
31
 
31
32
  # Include all route modules
32
33
  router.include_router(access.router, tags=["Access"])
34
+ router.include_router(accounts.router, tags=["Accounts"])
33
35
  router.include_router(awards.router, tags=["Awards"])
34
36
  router.include_router(clarifications.router, tags=["Clarifications"])
35
37
  router.include_router(contests.router, tags=["Contests"])
@@ -11,10 +11,8 @@ logger = logging.getLogger(__name__)
11
11
 
12
12
  @router.get(
13
13
  "/contests/{contest_id}/access",
14
- summary="Get Access Information",
15
- description="Get access capabilities and visible endpoints for current client",
14
+ summary="Get access information",
16
15
  response_model=Dict[str, Any],
17
16
  )
18
17
  async def get_access(contest_id: str, service: ContestServiceDep) -> Dict[str, Any]:
19
- """Get access information for the current client"""
20
- return service.get_access_info(contest_id)
18
+ return service.get_access(contest_id)
@@ -0,0 +1,35 @@
1
+ import logging
2
+ from typing import Any, Dict, List
3
+
4
+ from fastapi import APIRouter
5
+ from fastapi import Path as FastAPIPath
6
+
7
+ from ..dependencies import ContestServiceDep
8
+
9
+ router = APIRouter()
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ @router.get(
14
+ "/contests/{contest_id}/accounts",
15
+ summary="Get all the accounts",
16
+ response_model=List[Dict[str, Any]],
17
+ )
18
+ async def get_accounts(
19
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
20
+ service: ContestServiceDep = None,
21
+ ) -> List[Dict[str, Any]]:
22
+ return service.get_accounts(contest_id)
23
+
24
+
25
+ @router.get(
26
+ "/contests/{contest_id}/accounts/{account_id}",
27
+ summary="Get the given account",
28
+ response_model=Dict[str, Any],
29
+ )
30
+ async def get_account(
31
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
32
+ account_id: str = FastAPIPath(..., description="Account identifier"),
33
+ service: ContestServiceDep = None,
34
+ ) -> Dict[str, Any]:
35
+ return service.get_account(contest_id, account_id)
@@ -3,7 +3,6 @@ from typing import Any, Dict, List
3
3
 
4
4
  from fastapi import APIRouter, Path
5
5
 
6
- from ...model import Award, Awards
7
6
  from ..dependencies import ContestServiceDep
8
7
 
9
8
  router = APIRouter()
@@ -12,27 +11,23 @@ logger = logging.getLogger(__name__)
12
11
 
13
12
  @router.get(
14
13
  "/contests/{contest_id}/awards",
15
- summary="Get Awards",
16
- description="Get all awards in the contest",
17
- response_model=Awards,
14
+ summary="Get all the awards standings for this contest",
15
+ response_model=List[Dict[str, Any]],
18
16
  )
19
17
  async def get_awards(
20
18
  contest_id: str = Path(..., description="Contest identifier"), service: ContestServiceDep = None
21
19
  ) -> List[Dict[str, Any]]:
22
- """Get all awards"""
23
20
  return service.get_awards(contest_id)
24
21
 
25
22
 
26
23
  @router.get(
27
24
  "/contests/{contest_id}/awards/{award_id}",
28
- summary="Get Award",
29
- description="Get specific award information",
30
- response_model=Award,
25
+ summary="Get the specific award for this contest",
26
+ response_model=Dict[str, Any],
31
27
  )
32
28
  async def get_award(
33
29
  contest_id: str = Path(..., description="Contest identifier"),
34
30
  award_id: str = Path(..., description="Award identifier"),
35
31
  service: ContestServiceDep = None,
36
32
  ) -> Dict[str, Any]:
37
- """Get specific award information"""
38
33
  return service.get_award(contest_id, award_id)
@@ -1,9 +1,8 @@
1
1
  import logging
2
- from typing import Any, Dict, List, Optional
2
+ from typing import Any, Dict, List
3
3
 
4
- from fastapi import APIRouter, Path, Query
4
+ from fastapi import APIRouter, Path
5
5
 
6
- from ...model import Clarification, Clarifications
7
6
  from ..dependencies import ContestServiceDep
8
7
 
9
8
  router = APIRouter()
@@ -12,31 +11,24 @@ logger = logging.getLogger(__name__)
12
11
 
13
12
  @router.get(
14
13
  "/contests/{contest_id}/clarifications",
15
- summary="Get Clarifications",
16
- description="Get all clarifications, optionally filtered",
17
- response_model=Clarifications,
14
+ summary="Get all the clarifications for this contest",
15
+ response_model=List[Dict[str, Any]],
18
16
  )
19
17
  async def get_clarifications(
20
18
  contest_id: str = Path(..., description="Contest identifier"),
21
- from_team_id: Optional[str] = Query(None, description="Filter by sender team ID (empty string for null)"),
22
- to_team_id: Optional[str] = Query(None, description="Filter by recipient team ID (empty string for null)"),
23
- problem_id: Optional[str] = Query(None, description="Filter by problem ID (empty string for null)"),
24
19
  service: ContestServiceDep = None,
25
20
  ) -> List[Dict[str, Any]]:
26
- """Get all clarifications, optionally filtered"""
27
- return service.get_clarifications(contest_id, from_team_id, to_team_id, problem_id)
21
+ return service.get_clarifications(contest_id)
28
22
 
29
23
 
30
24
  @router.get(
31
25
  "/contests/{contest_id}/clarifications/{clarification_id}",
32
- summary="Get Clarification",
33
- description="Get specific clarification information",
34
- response_model=Clarification,
26
+ summary="Get the given clarifications for this contest",
27
+ response_model=Dict[str, Any],
35
28
  )
36
29
  async def get_clarification(
37
30
  contest_id: str = Path(..., description="Contest identifier"),
38
31
  clarification_id: str = Path(..., description="Clarification identifier"),
39
32
  service: ContestServiceDep = None,
40
33
  ) -> Dict[str, Any]:
41
- """Get specific clarification information"""
42
34
  return service.get_clarification(contest_id, clarification_id)
@@ -1,67 +1,66 @@
1
+ import json
1
2
  import logging
2
3
  from pathlib import Path
3
- from typing import Any, Dict, List
4
+ from typing import Any, Dict, List, Optional
4
5
 
5
- from fastapi import APIRouter, HTTPException
6
+ from fastapi import APIRouter, HTTPException, Query
6
7
  from fastapi import Path as FastAPIPath
7
- from fastapi.responses import FileResponse
8
+ from fastapi.responses import FileResponse, StreamingResponse
8
9
 
9
- from ...model import Contest, State
10
10
  from ..dependencies import ContestServiceDep
11
11
 
12
12
  router = APIRouter()
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
- @router.get("/contests", summary="Get Contests", description="Get list of all contests", response_model=List[Contest])
16
+ @router.get(
17
+ "/contests",
18
+ summary="Get all the contests",
19
+ response_model=List[Dict[str, Any]],
20
+ )
17
21
  async def get_contests(service: ContestServiceDep) -> List[Dict[str, Any]]:
18
- """Get all contests"""
19
22
  return service.get_contests()
20
23
 
21
24
 
22
25
  @router.get(
23
26
  "/contests/{contest_id}",
24
- summary="Get Contest",
25
- description="Get specific contest information",
26
- response_model=Contest,
27
+ summary="Get the given contest",
28
+ response_model=Dict[str, Any],
27
29
  )
28
30
  async def get_contest(
29
- contest_id: str = FastAPIPath(..., description="Contest identifier"), service: ContestServiceDep = None
31
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
32
+ service: ContestServiceDep = None,
30
33
  ) -> Dict[str, Any]:
31
- """Get specific contest information"""
32
34
  return service.get_contest(contest_id)
33
35
 
34
36
 
35
37
  @router.get(
36
38
  "/contests/{contest_id}/state",
37
- summary="Get Contest State",
38
- description="Get current contest state (started, ended, frozen, etc.)",
39
- response_model=State,
39
+ summary="Get the current contest state",
40
+ response_model=Dict[str, Any],
40
41
  )
41
42
  async def get_state(
42
- contest_id: str = FastAPIPath(..., description="Contest identifier"), service: ContestServiceDep = None
43
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
44
+ service: ContestServiceDep = None,
43
45
  ) -> Dict[str, Any]:
44
- """Get contest state"""
45
46
  return service.get_contest_state(contest_id)
46
47
 
47
48
 
48
49
  @router.get(
49
- "/contests/{contest_id}/contest/banner",
50
- summary="Get Contest Banner",
51
- description="Get banner image for the contest",
50
+ "/contests/{contest_id}/banner",
51
+ summary="Get the banner for the given contest",
52
52
  response_class=FileResponse,
53
53
  )
54
54
  async def get_contest_banner(
55
- contest_id: str = FastAPIPath(..., description="Contest identifier"), service: ContestServiceDep = None
55
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
56
+ service: ContestServiceDep = None,
56
57
  ) -> FileResponse:
57
- """Get contest banner file"""
58
58
  service.validate_contest_id(contest_id)
59
59
 
60
- # Expected href pattern for this endpoint
61
- expected_href = f"contests/{contest_id}/contest/banner"
60
+ expected_href = f"contests/{contest_id}/banner"
62
61
 
63
62
  try:
64
- banners = service.contest_data.get("banner", [])
63
+ banners = service.contest.get("banner", [])
65
64
  for banner in banners:
66
65
  href = banner["href"]
67
66
  if href == expected_href:
@@ -72,3 +71,49 @@ async def get_contest_banner(
72
71
  return FileResponse(path=banner_file, media_type=mime_type, filename=filename)
73
72
  except Exception as e:
74
73
  raise HTTPException(status_code=404, detail=f"Banner not found. [contest_id={contest_id}] [err={e}]")
74
+
75
+
76
+ @router.get(
77
+ "/contests/{contest_id}/problemset",
78
+ summary="Get the problemset document for the given contest",
79
+ response_class=FileResponse,
80
+ )
81
+ async def get_contest_problem_set(
82
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
83
+ service: ContestServiceDep = None,
84
+ ) -> FileResponse:
85
+ service.validate_contest_id(contest_id)
86
+
87
+ expected_href = f"contests/{contest_id}/problemset"
88
+
89
+ try:
90
+ problem_set_list = service.contest.get("problemset", [])
91
+ for problem_set in problem_set_list:
92
+ href = problem_set["href"]
93
+ if href == expected_href:
94
+ filename = problem_set["filename"]
95
+ problem_set_file: Path = service.contest_package_dir / "contest" / filename
96
+ if problem_set_file.exists():
97
+ mime_type = problem_set["mime"]
98
+ return FileResponse(path=problem_set_file, media_type=mime_type, filename=filename)
99
+ except Exception as e:
100
+ raise HTTPException(status_code=404, detail=f"Problem set not found. [contest_id={contest_id}] [err={e}]")
101
+
102
+
103
+ @router.get(
104
+ "/contests/{contest_id}/event-feed",
105
+ summary="Get event feed for contest",
106
+ description="Get events for the contest in NDJSON format. Each line contains a single event object.",
107
+ )
108
+ async def get_event_feed(
109
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
110
+ stream: bool = Query(False, description="Whether to stream the output or stop immediately"),
111
+ since_token: Optional[str] = Query(None, description="Return events after this token"),
112
+ service: ContestServiceDep = None,
113
+ ) -> StreamingResponse:
114
+ async def generate():
115
+ events = service.get_event_feed(contest_id, since_token)
116
+ for event in events:
117
+ yield json.dumps(event, ensure_ascii=False, separators=(",", ":")) + "\n"
118
+
119
+ return StreamingResponse(generate(), media_type="application/x-ndjson")
@@ -13,17 +13,18 @@ logger = logging.getLogger(__name__)
13
13
  @router.get(
14
14
  "/",
15
15
  summary="API Information",
16
- description="Get API version and provider information",
17
16
  response_model=Dict[str, Any],
18
17
  )
19
18
  async def get_api_info(service: ContestServiceDep) -> Dict[str, Any]:
20
- """Get API information and provider details"""
21
19
  return service.get_api_info()
22
20
 
23
21
 
24
- @router.get("/health", summary="Health Check", description="Check server health status", response_model=Dict[str, Any])
22
+ @router.get(
23
+ "/health",
24
+ summary="Health Check",
25
+ response_model=Dict[str, Any],
26
+ )
25
27
  async def health_check(service: ContestServiceDep) -> Dict[str, Any]:
26
- """Health check endpoint"""
27
28
  return {
28
29
  "status": "healthy",
29
30
  "timestamp": datetime.now().isoformat(),
@@ -3,10 +3,6 @@ from typing import Any, Dict, List
3
3
 
4
4
  from fastapi import APIRouter, Path
5
5
 
6
- from ...model import (
7
- Group,
8
- Groups,
9
- )
10
6
  from ..dependencies import ContestServiceDep
11
7
 
12
8
  router = APIRouter()
@@ -15,27 +11,24 @@ logger = logging.getLogger(__name__)
15
11
 
16
12
  @router.get(
17
13
  "/contests/{contest_id}/groups",
18
- summary="Get Groups",
19
- description="Get all team groups in the contest",
20
- response_model=Groups,
14
+ summary="Get all the groups for this contest",
15
+ response_model=List[Dict[str, Any]],
21
16
  )
22
17
  async def get_groups(
23
- contest_id: str = Path(..., description="Contest identifier"), service: ContestServiceDep = None
18
+ contest_id: str = Path(..., description="Contest identifier"),
19
+ service: ContestServiceDep = None,
24
20
  ) -> List[Dict[str, Any]]:
25
- """Get all groups"""
26
21
  return service.get_groups(contest_id)
27
22
 
28
23
 
29
24
  @router.get(
30
25
  "/contests/{contest_id}/groups/{group_id}",
31
- summary="Get Group",
32
- description="Get specific group information",
33
- response_model=Group,
26
+ summary="Get the given group for this contest",
27
+ response_model=Dict[str, Any],
34
28
  )
35
29
  async def get_group(
36
30
  contest_id: str = Path(..., description="Contest identifier"),
37
31
  group_id: str = Path(..., description="Group identifier"),
38
32
  service: ContestServiceDep = None,
39
33
  ) -> Dict[str, Any]:
40
- """Get specific group information"""
41
34
  return service.get_group(contest_id, group_id)
@@ -3,10 +3,6 @@ from typing import Any, Dict, List
3
3
 
4
4
  from fastapi import APIRouter, Path
5
5
 
6
- from ...model import (
7
- JudgementType,
8
- JudgementTypes,
9
- )
10
6
  from ..dependencies import ContestServiceDep
11
7
 
12
8
  router = APIRouter()
@@ -15,27 +11,24 @@ logger = logging.getLogger(__name__)
15
11
 
16
12
  @router.get(
17
13
  "/contests/{contest_id}/judgement-types",
18
- summary="Get Judgement Types",
19
- description="Get all judgement types available in the contest",
20
- response_model=JudgementTypes,
14
+ summary="Get all the judgement types for this contest",
15
+ response_model=List[Dict[str, Any]],
21
16
  )
22
17
  async def get_judgement_types(
23
- contest_id: str = Path(..., description="Contest identifier"), service: ContestServiceDep = None
18
+ contest_id: str = Path(..., description="Contest identifier"),
19
+ service: ContestServiceDep = None,
24
20
  ) -> List[Dict[str, Any]]:
25
- """Get all judgement types"""
26
21
  return service.get_judgement_types(contest_id)
27
22
 
28
23
 
29
24
  @router.get(
30
25
  "/contests/{contest_id}/judgement-types/{judgement_type_id}",
31
- summary="Get Judgement Type",
32
- description="Get specific judgement type information",
33
- response_model=JudgementType,
26
+ summary="Get the given judgement type for this contest",
27
+ response_model=Dict[str, Any],
34
28
  )
35
29
  async def get_judgement_type(
36
30
  contest_id: str = Path(..., description="Contest identifier"),
37
31
  judgement_type_id: str = Path(..., description="Judgement type identifier"),
38
32
  service: ContestServiceDep = None,
39
33
  ) -> Dict[str, Any]:
40
- """Get specific judgement type information"""
41
34
  return service.get_judgement_type(contest_id, judgement_type_id)
@@ -3,7 +3,6 @@ from typing import Any, Dict, List, Optional
3
3
 
4
4
  from fastapi import APIRouter, Path, Query
5
5
 
6
- from ...model import Judgement, Judgements
7
6
  from ..dependencies import ContestServiceDep
8
7
 
9
8
  router = APIRouter()
@@ -12,29 +11,25 @@ logger = logging.getLogger(__name__)
12
11
 
13
12
  @router.get(
14
13
  "/contests/{contest_id}/judgements",
15
- summary="Get Judgements",
16
- description="Get all judgements, optionally filtered by submission",
17
- response_model=Judgements,
14
+ summary="Get all the judgements for this contest",
15
+ response_model=List[Dict[str, Any]],
18
16
  )
19
17
  async def get_judgements(
20
18
  contest_id: str = Path(..., description="Contest identifier"),
21
19
  submission_id: Optional[str] = Query(None, description="Filter judgements by submission ID"),
22
20
  service: ContestServiceDep = None,
23
21
  ) -> List[Dict[str, Any]]:
24
- """Get all judgements, optionally filtered by submission"""
25
22
  return service.get_judgements(contest_id, submission_id)
26
23
 
27
24
 
28
25
  @router.get(
29
26
  "/contests/{contest_id}/judgements/{judgement_id}",
30
- summary="Get Judgement",
31
- description="Get specific judgement information",
32
- response_model=Judgement,
27
+ summary="Get the given judgement for this contest",
28
+ response_model=Dict[str, Any],
33
29
  )
34
30
  async def get_judgement(
35
31
  contest_id: str = Path(..., description="Contest identifier"),
36
32
  judgement_id: str = Path(..., description="Judgement identifier"),
37
33
  service: ContestServiceDep = None,
38
34
  ) -> Dict[str, Any]:
39
- """Get specific judgement information"""
40
35
  return service.get_judgement(contest_id, judgement_id)
@@ -3,10 +3,6 @@ from typing import Any, Dict, List
3
3
 
4
4
  from fastapi import APIRouter, Path
5
5
 
6
- from ...model import (
7
- Language,
8
- Languages,
9
- )
10
6
  from ..dependencies import ContestServiceDep
11
7
 
12
8
  router = APIRouter()
@@ -15,27 +11,24 @@ logger = logging.getLogger(__name__)
15
11
 
16
12
  @router.get(
17
13
  "/contests/{contest_id}/languages",
18
- summary="Get Languages",
19
- description="Get all programming languages available for submission",
20
- response_model=Languages,
14
+ summary="Get all the languages for this contest",
15
+ response_model=List[Dict[str, Any]],
21
16
  )
22
17
  async def get_languages(
23
- contest_id: str = Path(..., description="Contest identifier"), service: ContestServiceDep = None
18
+ contest_id: str = Path(..., description="Contest identifier"),
19
+ service: ContestServiceDep = None,
24
20
  ) -> List[Dict[str, Any]]:
25
- """Get all programming languages"""
26
21
  return service.get_languages(contest_id)
27
22
 
28
23
 
29
24
  @router.get(
30
25
  "/contests/{contest_id}/languages/{language_id}",
31
- summary="Get Language",
32
- description="Get specific language information",
33
- response_model=Language,
26
+ summary="Get the given language for this contest",
27
+ response_model=Dict[str, Any],
34
28
  )
35
29
  async def get_language(
36
30
  contest_id: str = Path(..., description="Contest identifier"),
37
31
  language_id: str = Path(..., description="Language identifier"),
38
32
  service: ContestServiceDep = None,
39
33
  ) -> Dict[str, Any]:
40
- """Get specific language information"""
41
34
  return service.get_language(contest_id, language_id)
@@ -6,10 +6,6 @@ from fastapi import APIRouter, HTTPException
6
6
  from fastapi import Path as FastAPIPath
7
7
  from fastapi.responses import FileResponse
8
8
 
9
- from ...model import (
10
- Organization,
11
- Organizations,
12
- )
13
9
  from ..dependencies import ContestServiceDep
14
10
 
15
11
  router = APIRouter()
@@ -18,36 +14,32 @@ logger = logging.getLogger(__name__)
18
14
 
19
15
  @router.get(
20
16
  "/contests/{contest_id}/organizations",
21
- summary="Get Organizations",
22
- description="Get all organizations in the contest",
23
- response_model=Organizations,
17
+ summary="Get all the organizations for this contest",
18
+ response_model=List[Dict[str, Any]],
24
19
  )
25
20
  async def get_organizations(
26
- contest_id: str = FastAPIPath(..., description="Contest identifier"), service: ContestServiceDep = None
21
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
22
+ service: ContestServiceDep = None,
27
23
  ) -> List[Dict[str, Any]]:
28
- """Get all organizations"""
29
24
  return service.get_organizations(contest_id)
30
25
 
31
26
 
32
27
  @router.get(
33
28
  "/contests/{contest_id}/organizations/{organization_id}",
34
- summary="Get Organization",
35
- description="Get specific organization information",
36
- response_model=Organization,
29
+ summary="Get the given organization for this contest",
30
+ response_model=Dict[str, Any],
37
31
  )
38
32
  async def get_organization(
39
33
  contest_id: str = FastAPIPath(..., description="Contest identifier"),
40
34
  organization_id: str = FastAPIPath(..., description="Organization identifier"),
41
35
  service: ContestServiceDep = None,
42
36
  ) -> Dict[str, Any]:
43
- """Get specific organization information"""
44
37
  return service.get_organization(contest_id, organization_id)
45
38
 
46
39
 
47
40
  @router.get(
48
41
  "/contests/{contest_id}/organizations/{organization_id}/logo",
49
42
  summary="Get Organization Logo",
50
- description="Get logo file for a specific organization",
51
43
  response_class=FileResponse,
52
44
  )
53
45
  async def get_organization_logo(
@@ -55,15 +47,12 @@ async def get_organization_logo(
55
47
  organization_id: str = FastAPIPath(..., description="Organization identifier"),
56
48
  service: ContestServiceDep = None,
57
49
  ) -> FileResponse:
58
- """Get organization logo file"""
59
50
  service.validate_contest_id(contest_id)
60
51
 
61
- # Get organization from indexed data
62
52
  org = service.organizations_by_id.get(organization_id)
63
53
  if not org:
64
54
  raise HTTPException(status_code=404, detail=f"Organization {organization_id} not found")
65
55
 
66
- # Expected href pattern for this endpoint
67
56
  expected_href = f"contests/{contest_id}/organizations/{organization_id}/logo"
68
57
 
69
58
  try:
@@ -6,7 +6,6 @@ from fastapi import APIRouter, HTTPException
6
6
  from fastapi import Path as FastAPIPath
7
7
  from fastapi.responses import FileResponse
8
8
 
9
- from ...model import Problem, Problems
10
9
  from ..dependencies import ContestServiceDep
11
10
 
12
11
  router = APIRouter()
@@ -15,36 +14,32 @@ logger = logging.getLogger(__name__)
15
14
 
16
15
  @router.get(
17
16
  "/contests/{contest_id}/problems",
18
- summary="Get Problems",
19
- description="Get all problems in the contest",
20
- response_model=Problems,
17
+ summary="Get all the problems for this contest",
18
+ response_model=List[Dict[str, Any]],
21
19
  )
22
20
  async def get_problems(
23
- contest_id: str = FastAPIPath(..., description="Contest identifier"), service: ContestServiceDep = None
21
+ contest_id: str = FastAPIPath(..., description="Contest identifier"),
22
+ service: ContestServiceDep = None,
24
23
  ) -> List[Dict[str, Any]]:
25
- """Get all problems in the contest"""
26
24
  return service.get_problems(contest_id)
27
25
 
28
26
 
29
27
  @router.get(
30
28
  "/contests/{contest_id}/problems/{problem_id}",
31
- summary="Get Problem",
32
- description="Get specific problem information",
33
- response_model=Problem,
29
+ summary="Get the given problem for this contest",
30
+ response_model=Dict[str, Any],
34
31
  )
35
32
  async def get_problem(
36
33
  contest_id: str = FastAPIPath(..., description="Contest identifier"),
37
34
  problem_id: str = FastAPIPath(..., description="Problem identifier"),
38
35
  service: ContestServiceDep = None,
39
36
  ) -> Dict[str, Any]:
40
- """Get specific problem information"""
41
37
  return service.get_problem(contest_id, problem_id)
42
38
 
43
39
 
44
40
  @router.get(
45
41
  "/contests/{contest_id}/problems/{problem_id}/statement",
46
42
  summary="Get Problem Statement",
47
- description="Get problem statement file",
48
43
  response_class=FileResponse,
49
44
  )
50
45
  async def get_problem_statement(
@@ -52,15 +47,12 @@ async def get_problem_statement(
52
47
  problem_id: str = FastAPIPath(..., description="Problem identifier"),
53
48
  service: ContestServiceDep = None,
54
49
  ) -> FileResponse:
55
- """Get problem statement file"""
56
50
  service.validate_contest_id(contest_id)
57
51
 
58
- # Get problem from indexed data
59
52
  problem: Dict = service.problems_by_id.get(problem_id)
60
53
  if not problem:
61
54
  raise HTTPException(status_code=404, detail=f"Problem {problem_id} not found")
62
55
 
63
- # Expected href pattern for this endpoint
64
56
  expected_href = f"contests/{contest_id}/problems/{problem_id}/statement"
65
57
 
66
58
  try: