icpc-api 0.1.0__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.
Files changed (50) hide show
  1. icpc/__init__.py +32 -0
  2. icpc/api/__init__.py +18 -0
  3. icpc/api/common.py +97 -0
  4. icpc/api/contest.py +253 -0
  5. icpc/api/person.py +139 -0
  6. icpc/api/public.py +65 -0
  7. icpc/api/staff.py +83 -0
  8. icpc/api/team.py +335 -0
  9. icpc/auth/__init__.py +28 -0
  10. icpc/auth/cognito.py +142 -0
  11. icpc/auth/flows.py +314 -0
  12. icpc/auth/provider.py +29 -0
  13. icpc/auth/srp.py +185 -0
  14. icpc/auth/store.py +223 -0
  15. icpc/auth/tokens.py +86 -0
  16. icpc/cli/__init__.py +20 -0
  17. icpc/cli/columns.py +555 -0
  18. icpc/cli/main.py +1156 -0
  19. icpc/cli/render.py +160 -0
  20. icpc/config.py +57 -0
  21. icpc/errors.py +159 -0
  22. icpc/facade/__init__.py +6 -0
  23. icpc/facade/client.py +606 -0
  24. icpc/facade/domain.py +198 -0
  25. icpc/models/__init__.py +60 -0
  26. icpc/models/_generated.py +566 -0
  27. icpc/models/base.py +41 -0
  28. icpc/models/blobs.py +81 -0
  29. icpc/models/common.py +61 -0
  30. icpc/models/entities.py +522 -0
  31. icpc/models/enums.py +192 -0
  32. icpc/models/mixins.py +44 -0
  33. icpc/py.typed +0 -0
  34. icpc/search/__init__.py +99 -0
  35. icpc/search/_generated.py +1814 -0
  36. icpc/search/dsl.py +124 -0
  37. icpc/search/endpoint.py +173 -0
  38. icpc/search/fields.py +59 -0
  39. icpc/transport/__init__.py +29 -0
  40. icpc/transport/_shared.py +121 -0
  41. icpc/transport/async_client.py +120 -0
  42. icpc/transport/operation.py +139 -0
  43. icpc/transport/sync_client.py +121 -0
  44. icpc_api-0.1.0.dist-info/METADATA +143 -0
  45. icpc_api-0.1.0.dist-info/RECORD +50 -0
  46. icpc_api-0.1.0.dist-info/WHEEL +5 -0
  47. icpc_api-0.1.0.dist-info/entry_points.txt +2 -0
  48. icpc_api-0.1.0.dist-info/licenses/LICENSE +21 -0
  49. icpc_api-0.1.0.dist-info/licenses/THIRD-PARTY-LICENSES.md +220 -0
  50. icpc_api-0.1.0.dist-info/top_level.txt +1 -0
icpc/models/enums.py ADDED
@@ -0,0 +1,192 @@
1
+ """Wire enumerations.
2
+
3
+ Server returns these lists from the ``/aspectfaces`` form registry. Model fields
4
+ are typed ``Enum | str`` so that unrecognised values arrive as strings.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from enum import StrEnum
10
+
11
+ __all__ = [
12
+ "Consent",
13
+ "ContestType",
14
+ "EligibilityStatus",
15
+ "ExportType",
16
+ "InstitutionUnitType",
17
+ "MemberRole",
18
+ "ParticipantRole",
19
+ "PublicPagesVisibility",
20
+ "Sex",
21
+ "ShirtSize",
22
+ "TeamStatus",
23
+ "Title",
24
+ "coach_roles",
25
+ "contestant_roles",
26
+ ]
27
+
28
+
29
+ class TeamStatus(StrEnum):
30
+ """Team registration status. Complete, from ``…team.businessobjects.Team``.
31
+
32
+ The frontend labels the third one "Rejected"; the wire value is ``CANCELED``.
33
+ """
34
+
35
+ PENDING = "PENDING"
36
+ ACCEPTED = "ACCEPTED"
37
+ CANCELED = "CANCELED"
38
+
39
+
40
+ class MemberRole(StrEnum):
41
+ """A person's role on a team, from ``…team.businessobjects.TeamMember``."""
42
+
43
+ COACH = "COACH"
44
+ COCOACH = "COCOACH"
45
+ #: A contestant who also coaches: counted as *both* a contestant and a coach.
46
+ CONTESTANT_COACH = "CONTESTANT_COACH"
47
+ CONTESTANT = "CONTESTANT"
48
+ ATTENDEE = "ATTENDEE"
49
+ RESERVE = "RESERVE"
50
+ STAFF = "STAFF"
51
+ #: Not in the server's current option list, but older contests may still
52
+ #: carry it. Treated like ``CONTESTANT_COACH``: both a contestant and a coach.
53
+ STUDENT_COACH = "STUDENT_COACH"
54
+
55
+
56
+ class ParticipantRole(StrEnum):
57
+ """A person's role at a contest, independent of any team."""
58
+
59
+ CONTESTANT = "CONTESTANT"
60
+ COACH = "COACH"
61
+ COCOACH = "COCOACH"
62
+ RESERVE = "RESERVE"
63
+ ATTENDEE = "ATTENDEE"
64
+ STAFF = "STAFF"
65
+
66
+
67
+ class Consent(StrEnum):
68
+ """A registration consent answer.
69
+
70
+ Several columns read like booleans — ``includeEmail``,
71
+ ``employmentOpportunities``, ``informOtherContests``, ``inform``, ``icpcRules``,
72
+ ``mediaUse`` — but the wire carries words, so ``bool`` simply fails to parse.
73
+ Complete, from ``…person.businessobjects.PersonInfoAbstract``.
74
+ """
75
+
76
+ AGREE = "AGREE"
77
+ DISAGREE = "DISAGREE"
78
+
79
+
80
+ class Sex(StrEnum):
81
+ """Complete, from ``…person.businessobjects.PersonInfoAbstract``."""
82
+
83
+ FEMALE = "FEMALE"
84
+ MALE = "MALE"
85
+
86
+
87
+ class EligibilityStatus(StrEnum):
88
+ """Eligibility verdict on a team.
89
+
90
+ Complete, from ``…team.businessobjects.Eligibility``. A full-object team write
91
+ recomputes this and drops any ``VERIFIED_*`` value.
92
+ """
93
+
94
+ NOT_RESOLVED = "NOT_RESOLVED"
95
+ NO_ISSUES_FOUND = "NO_ISSUES_FOUND"
96
+ PREDICTED_INELIGIBLE = "PREDICTED_INELIGIBLE"
97
+ VERIFIED_ELIGIBLE = "VERIFIED_ELIGIBLE"
98
+ VERIFIED_INELIGIBLE = "VERIFIED_INELIGIBLE"
99
+ ELIGIBILITY_CHECK_NOT_REQUIRED = "ELIGIBILITY_CHECK_NOT_REQUIRED"
100
+ VALIDATED_BY_LOWER_CONTEST = "VALIDATED_BY_LOWER_CONTEST"
101
+
102
+
103
+ class ContestType(StrEnum):
104
+ """Complete, from ``…contest.businessobjects.ContestSettings``."""
105
+
106
+ WORLD_FINALS = "WORLD_FINALS"
107
+ REGIONALS = "REGIONALS"
108
+ QUALIFIER = "QUALIFIER"
109
+ PRACTICE = "PRACTICE"
110
+ CAMP = "CAMP"
111
+
112
+
113
+ class PublicPagesVisibility(StrEnum):
114
+ """Whether a contest's public pages list people. Not a boolean, despite the name.
115
+
116
+ Complete, from ``…contest.businessobjects.ContestSettings``.
117
+ """
118
+
119
+ WITH_PEOPLE = "WITH_PEOPLE"
120
+ WITHOUT_PEOPLE = "WITHOUT_PEOPLE"
121
+
122
+
123
+ class Title(StrEnum):
124
+ """Complete, from ``…person.businessobjects.PersonInfoAbstract``."""
125
+
126
+ DR = "DR"
127
+ DRS = "DRS"
128
+ IR = "IR"
129
+ MISS = "MISS"
130
+ MR = "MR"
131
+ MRS = "MRS"
132
+ MS = "MS"
133
+ PROFESSOR = "PROFESSOR"
134
+ NONE = "NONE"
135
+
136
+
137
+ class InstitutionUnitType(StrEnum):
138
+ """What kind of institution a unit is.
139
+
140
+ Observed values only: the ``InstitutionUnit`` schema endpoint answers 500.
141
+ """
142
+
143
+ UNIVERSITY_GRADUATE = "UNIVERSITY_GRADUATE"
144
+ UNIVERSITY_NO_GRADUATE = "UNIVERSITY_NO_GRADUATE"
145
+ HIGH_SCHOOL = "HIGH_SCHOOL"
146
+
147
+
148
+ class ShirtSize(StrEnum):
149
+ """Complete, from ``…person.businessobjects.PersonInfoAbstract``."""
150
+
151
+ XS = "XS"
152
+ S = "S"
153
+ M = "M"
154
+ L = "L"
155
+ XL = "XL"
156
+ XXL = "XXL"
157
+ XXXL = "XXXL"
158
+ XXXXL = "XXXXL"
159
+ XXXXXL = "XXXXXL"
160
+
161
+
162
+ class ExportType(StrEnum):
163
+ """Formats accepted by the ``/export`` sibling of a search endpoint."""
164
+
165
+ CSV = "CSV"
166
+ TSV = "TSV"
167
+ TAB = "TAB"
168
+ TXT = "TXT"
169
+ EXCEL = "EXCEL"
170
+
171
+
172
+ def contestant_roles() -> frozenset[str]:
173
+ """Roles that count as competing."""
174
+ return frozenset(
175
+ {
176
+ MemberRole.CONTESTANT,
177
+ MemberRole.STUDENT_COACH,
178
+ MemberRole.CONTESTANT_COACH,
179
+ }
180
+ )
181
+
182
+
183
+ def coach_roles() -> frozenset[str]:
184
+ """Roles that count as coaching."""
185
+ return frozenset(
186
+ {
187
+ MemberRole.COACH,
188
+ MemberRole.COCOACH,
189
+ MemberRole.STUDENT_COACH,
190
+ MemberRole.CONTESTANT_COACH,
191
+ }
192
+ )
icpc/models/mixins.py ADDED
@@ -0,0 +1,44 @@
1
+ """Behaviour attached to generated rows that carry JSON-in-a-string columns.
2
+
3
+ The annotations are under ``TYPE_CHECKING`` on purpose: pydantic collects fields
4
+ from every base class's annotations, and re-declaring them here would fight with the
5
+ generated ones. At runtime these are plain attribute reads on the model.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import TYPE_CHECKING
11
+
12
+ from icpc.models.blobs import TeamMemberBlob, parse_extra_fields, parse_members
13
+
14
+ __all__ = ["HasExtraFields", "HasTeamMembers"]
15
+
16
+
17
+ class HasTeamMembers:
18
+ """A row whose ``teamMembers`` column holds the roster as a JSON string."""
19
+
20
+ if TYPE_CHECKING:
21
+ team_members: str | None
22
+
23
+ @property
24
+ def member_blobs(self) -> list[TeamMemberBlob]:
25
+ """The roster embedded in this row. Useful if ``teammember`` was not
26
+ fetched.
27
+ """
28
+ return parse_members(self.team_members)
29
+
30
+
31
+ class HasExtraFields:
32
+ """A row whose ``extraField`` column holds custom-question answers."""
33
+
34
+ if TYPE_CHECKING:
35
+ extra_field: str | None
36
+
37
+ @property
38
+ def extras(self) -> dict[str, str]:
39
+ """Answers to the contest's custom registration questions.
40
+
41
+ Keys are the contest's own question labels, so they differ between
42
+ contests and are frequently not in English.
43
+ """
44
+ return parse_extra_fields(self.extra_field)
icpc/py.typed ADDED
File without changes
@@ -0,0 +1,99 @@
1
+ """The ``q=`` search DSL, typed columns, and the generated endpoint catalogue."""
2
+
3
+ from icpc.search import _generated as endpoints
4
+ from icpc.search._generated import (
5
+ CertificateFields,
6
+ ContestParticipantFields,
7
+ InstitutionFields,
8
+ PromoteFields,
9
+ StaffFields,
10
+ StaffFundingFields,
11
+ StaffMemberFields,
12
+ StaffTshirtFields,
13
+ StandingsFields,
14
+ TeamFields,
15
+ TeamMemberFields,
16
+ TeamSummaryFields,
17
+ Top20Fields,
18
+ TransportationMissingFields,
19
+ TshirtFields,
20
+ contest_institutions,
21
+ contest_missing_transportation,
22
+ contest_participants,
23
+ contest_promote_candidates,
24
+ contest_public_staff_members,
25
+ contest_staff,
26
+ contest_staff_certificates,
27
+ contest_staff_funding,
28
+ contest_staff_members,
29
+ contest_staff_tshirts,
30
+ contest_standings,
31
+ contest_team_certificates,
32
+ contest_team_members,
33
+ contest_team_summaries,
34
+ contest_teams,
35
+ contest_top20,
36
+ site_coach_tshirts,
37
+ site_cocoach_tshirts,
38
+ site_contestant_tshirts,
39
+ site_home_teams,
40
+ site_institutions,
41
+ site_participants,
42
+ site_team_certificates,
43
+ site_team_members,
44
+ site_teams,
45
+ )
46
+ from icpc.search.dsl import Direction, Filter, FilterMode, Q, SortKey
47
+ from icpc.search.endpoint import SearchEndpoint
48
+ from icpc.search.fields import Field
49
+
50
+ __all__ = [
51
+ "CertificateFields",
52
+ "ContestParticipantFields",
53
+ "Direction",
54
+ "Field",
55
+ "Filter",
56
+ "FilterMode",
57
+ "InstitutionFields",
58
+ "PromoteFields",
59
+ "Q",
60
+ "SearchEndpoint",
61
+ "SortKey",
62
+ "StaffFields",
63
+ "StaffFundingFields",
64
+ "StaffMemberFields",
65
+ "StaffTshirtFields",
66
+ "StandingsFields",
67
+ "TeamFields",
68
+ "TeamMemberFields",
69
+ "TeamSummaryFields",
70
+ "Top20Fields",
71
+ "TransportationMissingFields",
72
+ "TshirtFields",
73
+ "contest_institutions",
74
+ "contest_missing_transportation",
75
+ "contest_participants",
76
+ "contest_promote_candidates",
77
+ "contest_public_staff_members",
78
+ "contest_staff",
79
+ "contest_staff_certificates",
80
+ "contest_staff_funding",
81
+ "contest_staff_members",
82
+ "contest_staff_tshirts",
83
+ "contest_standings",
84
+ "contest_team_certificates",
85
+ "contest_team_members",
86
+ "contest_team_summaries",
87
+ "contest_teams",
88
+ "contest_top20",
89
+ "endpoints",
90
+ "site_coach_tshirts",
91
+ "site_cocoach_tshirts",
92
+ "site_contestant_tshirts",
93
+ "site_home_teams",
94
+ "site_institutions",
95
+ "site_participants",
96
+ "site_team_certificates",
97
+ "site_team_members",
98
+ "site_teams",
99
+ ]