Campus API (campus.api)¶
The /api/v1 service: assignments, circles, files, hosted apps,
submissions, and timetable. Address collections directly
(campus.api.assignments.list()), single items by id
(campus.api.circles["circle_ab12cd34"].get()), and drill into
sub-resources (... submissions["sub_1"].feedback.add(...)).
All methods raise the mapped
APIError subclass on non-2xx
responses. Records deserialize to campus.model classes, except
files, which are plain validated dicts.
Note: campus.model.* types are documented in the
campus repo; signatures
here reference them without cross-links.
Assignments¶
campus_python.api.v1.assignments.Assignments
¶
Bases: ResourceCollection
Campus API Assignments resource.
Source code in campus_python/api/v1/assignments.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
path = 'assignments'
class-attribute
instance-attribute
¶
Assignment
¶
Bases: Resource
Single campus API assignment resource.
Source code in campus_python/api/v1/assignments.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
links: Assignments.Assignment.Links
property
¶
Get the links resource for this assignment.
Links
¶
Bases: Resource
Campus API Assignment Links resource.
Source code in campus_python/api/v1/assignments.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
add(*, course_id: str, coursework_id: str, attachment_id: str | None = None) -> None
¶
Attach a Google Classroom course/coursework link.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
course_id
|
str
|
Classroom course ID. |
required |
coursework_id
|
str
|
Classroom coursework ID. |
required |
attachment_id
|
str | None
|
Optional Drive attachment ID. |
None
|
Source code in campus_python/api/v1/assignments.py
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
delete() -> None
¶
Delete this assignment.
Source code in campus_python/api/v1/assignments.py
75 76 77 | |
get() -> campus.model.Assignment
¶
Get this assignment.
Returns:
| Type | Description |
|---|---|
Assignment
|
The Assignment. |
Source code in campus_python/api/v1/assignments.py
79 80 81 82 83 84 85 86 | |
update(**fields) -> None
¶
Update this assignment with the given fields.
The server rejects an empty PATCH body, so at least one field must be provided.
Source code in campus_python/api/v1/assignments.py
88 89 90 91 92 93 94 95 | |
__getitem__(assignment_id: str) -> Assignments.Assignment
¶
Get a specific assignment resource by ID.
Source code in campus_python/api/v1/assignments.py
15 16 17 | |
list(*, created_by: str | None = None) -> list[campus.model.Assignment]
¶
List all assignments matching filter requirements.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
created_by
|
str | None
|
Filter by teacher who created the assignment |
None
|
Returns:
| Type | Description |
|---|---|
list[Assignment]
|
List of Assignment objects |
Source code in campus_python/api/v1/assignments.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
new(*, title: str, description: str | None = None, questions: list[dict] | None = None, classroom_links: list[dict] | None = None) -> campus.model.Assignment
¶
Create a new assignment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
Assignment title (required by the server). |
required |
description
|
str | None
|
Assignment description. |
None
|
questions
|
list[dict] | None
|
Question definitions. |
None
|
classroom_links
|
list[dict] | None
|
Google Classroom course/coursework links. |
None
|
Returns:
| Type | Description |
|---|---|
Assignment
|
The created Assignment. |
Source code in campus_python/api/v1/assignments.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
Circles¶
campus_python.api.v1.circles.Circles
¶
Bases: ResourceCollection
Campus API Circles resource.
Source code in campus_python/api/v1/circles.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
path = 'circles'
class-attribute
instance-attribute
¶
Circle
¶
Bases: Resource
Single campus API circle resource.
Source code in campus_python/api/v1/circles.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
members: Circles.Circle.CircleMembers
property
¶
Get the members resource for this circle.
CircleMembers
¶
Bases: Resource
Campus API Circle Members resource.
Source code in campus_python/api/v1/circles.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
list() -> dict[str, int]
¶
Return the circle's {member_id: access_value} mapping.
Source code in campus_python/api/v1/circles.py
107 108 109 | |
add(member_id: str, access_value: int) -> None
¶
Add a member with an access value.
Targets the /members/add action route; adding an existing member re-errors server-side. Use set() for upsert semantics.
Source code in campus_python/api/v1/circles.py
111 112 113 114 115 116 117 118 119 120 121 | |
remove(member_id: str) -> None
¶
Remove a member.
Targets the /members/remove action route.
Source code in campus_python/api/v1/circles.py
123 124 125 126 127 128 129 130 131 | |
set(member_id: str, access_value: int) -> None
¶
Create or update a member's access value (upsert).
Unlike add()/remove(), which target the /members/add and /members/remove action routes, this PATCHes the members collection directly — the server's set semantics apply (no error when the access value is unchanged).
Source code in campus_python/api/v1/circles.py
133 134 135 136 137 138 139 140 141 142 143 144 145 | |
delete() -> None
¶
Delete this circle.
Source code in campus_python/api/v1/circles.py
68 69 70 | |
get() -> campus.model.Circle
¶
Get this circle.
Returns:
| Type | Description |
|---|---|
Circle
|
The Circle. |
Source code in campus_python/api/v1/circles.py
72 73 74 75 76 77 78 79 | |
update(*, name: str, description: str | None = None) -> None
¶
Update this circle.
The server requires name on every circle PATCH and returns 422 without it, so it is a required parameter here. Description is unchanged when omitted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
New circle name (must not collide with an existing circle's name) |
required |
description
|
str | None
|
New description; omitted leaves it unchanged |
None
|
Source code in campus_python/api/v1/circles.py
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | |
__getitem__(circle_id: str) -> Circles.Circle
¶
Get a specific circle resource by ID.
Source code in campus_python/api/v1/circles.py
17 18 19 | |
list() -> list[campus.model.Circle]
¶
List all circles.
Returns:
| Type | Description |
|---|---|
list[Circle]
|
List of Circle objects. |
Source code in campus_python/api/v1/circles.py
21 22 23 24 25 26 27 28 29 30 31 | |
new(*, name: str, tag: str, description: str = '', parents: dict[str, int] | None = None) -> campus.model.Circle
¶
Create a new circle.
The server rejects a name that collides with an existing circle (409).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Circle name (unique across Campus). |
required |
tag
|
str
|
Circle tag (e.g. "project"). |
required |
description
|
str
|
Circle description. |
''
|
parents
|
dict[str, int] | None
|
Parent circle ids mapped to access values. |
None
|
Returns:
| Type | Description |
|---|---|
Circle
|
The created Circle. |
Source code in campus_python/api/v1/circles.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | |
Files¶
The by-slug consumer surface (list / meta / content / upsert /
delete). Files are binary blobs addressed by a stable slug
(e.g. apps/quest-dom); slugs ride as raw path tails. Methods are
inherited from the shared
BySlugCollection
(see Extending the SDK); records are
plain dicts, not campus.model classes.
campus_python.api.v1.files.Files
¶
Bases: BySlugCollection[dict]
Campus API files resource (by-slug + id-based management).
Source code in campus_python/api/v1/files.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
path = 'files'
class-attribute
instance-attribute
¶
_client: Optional[JsonClient] = client
class-attribute
instance-attribute
¶
root: ResourceRoot = root
instance-attribute
¶
File
¶
Bases: Resource
A single file record addressed by id (management surface).
Unlike the by-slug upsert, these routes never create — replacing or reading content targets an existing record only (404 for an unknown id).
Source code in campus_python/api/v1/files.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
_client: Optional[JsonClient] = client
class-attribute
instance-attribute
¶
parent: Resource | ResourceCollection = parent
instance-attribute
¶
path: str = parent.make_path(SLASH.join(parts))
instance-attribute
¶
get() -> dict
¶
Get this file's metadata record.
Source code in campus_python/api/v1/files.py
35 36 37 | |
get_content() -> bytes
¶
Get this file's bytes — the CURRENT version.
Responses carry an ETag and a short max-age cache header. Content is returned undecoded — callers decode.
Source code in campus_python/api/v1/files.py
39 40 41 42 43 44 45 46 47 | |
put_content(data: bytes | str, content_type: str | None = None, name: str | None = None) -> dict
¶
Replace this file's content (never creates).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
bytes | str
|
Raw content (the request body). |
required |
content_type
|
str | None
|
MIME type to store and serve back (e.g. "text/html"); defaults to the transport's choice and upstream stores application/octet-stream when absent. |
None
|
name
|
str | None
|
Optional new display name (upstream's PUT ?name= parameter). |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The updated metadata record. |
Source code in campus_python/api/v1/files.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
delete() -> None
¶
Delete this file (its metadata and content).
Source code in campus_python/api/v1/files.py
78 79 80 81 | |
_get_json(path: str, query: JsonDict | None = None) -> Any
¶
GET path and return the parsed JSON body.
Source code in campus_python/interface.py
79 80 81 82 83 84 85 86 | |
_post_json(path: str, json: JsonDict | None = None) -> Any
¶
POST the JSON body and return the parsed JSON response body.
Source code in campus_python/interface.py
88 89 90 91 92 93 94 95 | |
_put_json(path: str, json: JsonDict, query: JsonDict | None = None) -> Any
¶
PUT the JSON body (with optional query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
_patch_json(path: str, json: Any, query: JsonDict | None = None) -> Any
¶
PATCH the JSON body (with optional query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
_delete_json(path: str, json: JsonDict | None = None, query: JsonDict | None = None) -> Any
¶
DELETE (optionally with a JSON body and/or query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
__init__(*parts: str, parent: Resource | ResourceCollection, client: Optional[JsonClient] = None)
¶
Source code in campus_python/interface.py
259 260 261 262 263 264 265 266 267 | |
__repr__() -> str
¶
Source code in campus_python/interface.py
269 270 | |
__str__() -> str
¶
Source code in campus_python/interface.py
272 273 | |
__getitem__(file_id: str) -> Files.File
¶
Get a file record's management surface by id.
Source code in campus_python/api/v1/files.py
23 24 25 | |
_get_json(path: str, query: JsonDict | None = None) -> Any
¶
GET path and return the parsed JSON body.
Source code in campus_python/interface.py
79 80 81 82 83 84 85 86 | |
_post_json(path: str, json: JsonDict | None = None) -> Any
¶
POST the JSON body and return the parsed JSON response body.
Source code in campus_python/interface.py
88 89 90 91 92 93 94 95 | |
_put_json(path: str, json: JsonDict, query: JsonDict | None = None) -> Any
¶
PUT the JSON body (with optional query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
_patch_json(path: str, json: Any, query: JsonDict | None = None) -> Any
¶
PATCH the JSON body (with optional query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
_delete_json(path: str, json: JsonDict | None = None, query: JsonDict | None = None) -> Any
¶
DELETE (optionally with a JSON body and/or query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
__init__(client: Optional[JsonClient] = None, *, root: ResourceRoot)
¶
Source code in campus_python/interface.py
204 205 206 207 208 209 210 211 | |
_from_resource(record: dict) -> Any
¶
Map a raw record dict to this surface's record type.
Default: pass the record through unchanged (dict-returning
surfaces). Model-backed surfaces override this, e.g. with
campus.model.HostedApp.from_resource.
Source code in campus_python/api/v1/byslug.py
28 29 30 31 32 33 34 35 | |
list(prefix: str | None = None) -> list[R]
¶
List records, optionally under a slug prefix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prefix
|
str | None
|
Only include records whose slug starts with this prefix. |
None
|
Returns:
| Type | Description |
|---|---|
list[R]
|
The records under the |
list[R]
|
mapped through _from_resource. |
Source code in campus_python/api/v1/byslug.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | |
get_meta(slug: str) -> R
¶
Get a record's metadata by slug (upstream's ?meta=1 query).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The record's stable slug, e.g. "apps/quest-dom". |
required |
Returns:
| Type | Description |
|---|---|
R
|
The record mapped through _from_resource. |
Source code in campus_python/api/v1/byslug.py
52 53 54 55 56 57 58 59 60 61 62 | |
get_content(slug: str) -> bytes
¶
Get a record's bytes by slug — the CURRENT version.
Responses carry an ETag and a short max-age cache header. Content is returned undecoded — callers decode.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The record's stable slug. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The content, as stored at serve time. |
Source code in campus_python/api/v1/byslug.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
put_by_slug(slug: str, data: bytes | str, content_type: str | None = None, name: str | None = None) -> R
¶
Create or replace a record's content by slug (upsert).
Replacing an existing slug keeps its address stable — consumers rely on this for in-place updates. Attribution (uploaded_by_client_id/user_id) is server-side from the bearer; user-session calls attribute to the user automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The stable slug to create or replace. |
required |
data
|
bytes | str
|
Raw content (the request body). |
required |
content_type
|
str | None
|
MIME type to store and serve back (e.g. "text/html"); defaults to the transport's choice and upstream stores application/octet-stream when absent. |
None
|
name
|
str | None
|
Optional display name, stored on the record for new records (upstream's PUT ?name= parameter). |
None
|
Returns:
| Type | Description |
|---|---|
R
|
The record mapped through _from_resource (201 shape on |
R
|
create, 200 shape on replace; identical dict fields). |
Source code in campus_python/api/v1/byslug.py
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
delete_by_slug(slug: str) -> None
¶
Delete a record (its metadata and content) by slug.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The slug to delete. |
required |
Source code in campus_python/api/v1/byslug.py
118 119 120 121 122 123 124 125 | |
_by_slug_path(slug: str) -> str
¶
Path for a by-slug route.
The slug is a path tail — slashes are part of the slug and
upstream's <path:slug> converter expects them literal — so
it is concatenated unquoted; make_path only trims a
leading/trailing slash.
Source code in campus_python/api/v1/byslug.py
127 128 129 130 131 132 133 134 135 | |
HostedApps¶
Single-file HTML apps published to Campus app hosting.
Content-addressed server-side: replacing content under a slug keeps
the slug's address while serving the new version. Methods are
inherited from
BySlugCollection;
records deserialize to campus.model.HostedApp. Unlike files,
upstream defaults content to text/html when no content type is
given.
campus_python.api.v1.hostedapps.HostedApps
¶
Bases: BySlugCollection[HostedApp]
Campus API hosted-apps resource (consumer-facing by-slug surface).
Source code in campus_python/api/v1/hostedapps.py
20 21 22 23 24 25 | |
path = 'hostedapps'
class-attribute
instance-attribute
¶
_client: Optional[JsonClient] = client
class-attribute
instance-attribute
¶
root: ResourceRoot = root
instance-attribute
¶
_from_resource(record: dict) -> campus.model.HostedApp
¶
Source code in campus_python/api/v1/hostedapps.py
24 25 | |
_get_json(path: str, query: JsonDict | None = None) -> Any
¶
GET path and return the parsed JSON body.
Source code in campus_python/interface.py
79 80 81 82 83 84 85 86 | |
_post_json(path: str, json: JsonDict | None = None) -> Any
¶
POST the JSON body and return the parsed JSON response body.
Source code in campus_python/interface.py
88 89 90 91 92 93 94 95 | |
_put_json(path: str, json: JsonDict, query: JsonDict | None = None) -> Any
¶
PUT the JSON body (with optional query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
_patch_json(path: str, json: Any, query: JsonDict | None = None) -> Any
¶
PATCH the JSON body (with optional query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
_delete_json(path: str, json: JsonDict | None = None, query: JsonDict | None = None) -> Any
¶
DELETE (optionally with a JSON body and/or query params) and return the parsed JSON response body.
Source code in campus_python/interface.py
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
__init__(client: Optional[JsonClient] = None, *, root: ResourceRoot)
¶
Source code in campus_python/interface.py
204 205 206 207 208 209 210 211 | |
list(prefix: str | None = None) -> list[R]
¶
List records, optionally under a slug prefix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prefix
|
str | None
|
Only include records whose slug starts with this prefix. |
None
|
Returns:
| Type | Description |
|---|---|
list[R]
|
The records under the |
list[R]
|
mapped through _from_resource. |
Source code in campus_python/api/v1/byslug.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | |
get_meta(slug: str) -> R
¶
Get a record's metadata by slug (upstream's ?meta=1 query).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The record's stable slug, e.g. "apps/quest-dom". |
required |
Returns:
| Type | Description |
|---|---|
R
|
The record mapped through _from_resource. |
Source code in campus_python/api/v1/byslug.py
52 53 54 55 56 57 58 59 60 61 62 | |
get_content(slug: str) -> bytes
¶
Get a record's bytes by slug — the CURRENT version.
Responses carry an ETag and a short max-age cache header. Content is returned undecoded — callers decode.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The record's stable slug. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The content, as stored at serve time. |
Source code in campus_python/api/v1/byslug.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
put_by_slug(slug: str, data: bytes | str, content_type: str | None = None, name: str | None = None) -> R
¶
Create or replace a record's content by slug (upsert).
Replacing an existing slug keeps its address stable — consumers rely on this for in-place updates. Attribution (uploaded_by_client_id/user_id) is server-side from the bearer; user-session calls attribute to the user automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The stable slug to create or replace. |
required |
data
|
bytes | str
|
Raw content (the request body). |
required |
content_type
|
str | None
|
MIME type to store and serve back (e.g. "text/html"); defaults to the transport's choice and upstream stores application/octet-stream when absent. |
None
|
name
|
str | None
|
Optional display name, stored on the record for new records (upstream's PUT ?name= parameter). |
None
|
Returns:
| Type | Description |
|---|---|
R
|
The record mapped through _from_resource (201 shape on |
R
|
create, 200 shape on replace; identical dict fields). |
Source code in campus_python/api/v1/byslug.py
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
delete_by_slug(slug: str) -> None
¶
Delete a record (its metadata and content) by slug.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
The slug to delete. |
required |
Source code in campus_python/api/v1/byslug.py
118 119 120 121 122 123 124 125 | |
_by_slug_path(slug: str) -> str
¶
Path for a by-slug route.
The slug is a path tail — slashes are part of the slug and
upstream's <path:slug> converter expects them literal — so
it is concatenated unquoted; make_path only trims a
leading/trailing slash.
Source code in campus_python/api/v1/byslug.py
127 128 129 130 131 132 133 134 135 | |
Submissions¶
campus_python.api.v1.submissions.Submissions
¶
Bases: ResourceCollection
Campus API Submissions resource.
Source code in campus_python/api/v1/submissions.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
path = 'submissions'
class-attribute
instance-attribute
¶
Submission
¶
Bases: Resource
Single campus API submission resource.
Source code in campus_python/api/v1/submissions.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
responses: Submissions.Submission.Responses
property
¶
Get the responses resource for this submission.
feedback: Submissions.Submission.Feedback
property
¶
Get the feedback resource for this submission.
Responses
¶
Bases: Resource
Campus API Submission Responses resource.
Source code in campus_python/api/v1/submissions.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
add(*, question_id: str, response_text: str) -> None
¶
Add or update a response to a question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
question_id
|
str
|
Question ID |
required |
response_text
|
str
|
Student's response text |
required |
Source code in campus_python/api/v1/submissions.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
Feedback
¶
Bases: Resource
Campus API Submission Feedback resource.
Source code in campus_python/api/v1/submissions.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
add(*, question_id: str, feedback_text: str) -> None
¶
Add feedback on a response to a question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
question_id
|
str
|
Question ID |
required |
feedback_text
|
str
|
Teacher's feedback text |
required |
Source code in campus_python/api/v1/submissions.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
delete() -> None
¶
Delete this submission.
Source code in campus_python/api/v1/submissions.py
124 125 126 | |
get() -> campus.model.Submission
¶
Get this submission.
Source code in campus_python/api/v1/submissions.py
128 129 130 131 | |
update(*, responses: list[dict] | None = None, feedback: list[dict] | None = None, submitted_at: str | None = None) -> None
¶
Update this submission.
All parameters are optional. Only provided fields will be updated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
responses
|
list[dict] | None
|
New list of responses |
None
|
feedback
|
list[dict] | None
|
New list of feedback |
None
|
submitted_at
|
str | None
|
New submitted_at timestamp |
None
|
Source code in campus_python/api/v1/submissions.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | |
submit() -> None
¶
Finalize/submit this submission (marks submitted_at timestamp).
Source code in campus_python/api/v1/submissions.py
156 157 158 159 160 | |
unsubmit() -> None
¶
Clear this submission's submitted_at timestamp.
The server only clears submitted_at for an explicit null in the PATCH body; update() cannot express that because None means "omit the field" there.
Source code in campus_python/api/v1/submissions.py
162 163 164 165 166 167 168 169 170 171 172 | |
__getitem__(submission_id: str) -> Submissions.Submission
¶
Get a specific submission resource by ID.
Source code in campus_python/api/v1/submissions.py
15 16 17 | |
list(*, assignment_id: str | None = None, student_id: str | None = None, course_id: str | None = None) -> list[campus.model.Submission]
¶
List all submissions matching filter requirements.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
assignment_id
|
str | None
|
Filter by assignment |
None
|
student_id
|
str | None
|
Filter by student |
None
|
course_id
|
str | None
|
Filter by Google Classroom course |
None
|
Returns:
| Type | Description |
|---|---|
list[Submission]
|
List of Submission objects |
Source code in campus_python/api/v1/submissions.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
by_assignment(assignment_id: str) -> list[campus.model.Submission]
¶
List submissions for a specific assignment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
assignment_id
|
str
|
Assignment ID |
required |
Returns:
| Type | Description |
|---|---|
list[Submission]
|
List of Submission objects |
Source code in campus_python/api/v1/submissions.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
by_student(student_id: str) -> list[campus.model.Submission]
¶
List submissions from a specific student.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
student_id
|
str
|
Student user ID |
required |
Returns:
| Type | Description |
|---|---|
list[Submission]
|
List of Submission objects |
Source code in campus_python/api/v1/submissions.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
new(*, assignment_id: str, student_id: str, course_id: str, responses: list[dict] | None = None) -> campus.model.Submission
¶
Create a new submission.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
assignment_id
|
str
|
Assignment ID |
required |
student_id
|
str
|
Student user ID |
required |
course_id
|
str
|
Google Classroom course ID |
required |
responses
|
list[dict] | None
|
List of response dictionaries |
None
|
Returns:
| Type | Description |
|---|---|
Submission
|
Created Submission object |
Source code in campus_python/api/v1/submissions.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | |
Timetable¶
campus_python.api.v1.timetable.Timetables
¶
Bases: ResourceCollection
Campus API Timetable resource.
Source code in campus_python/api/v1/timetable.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
path = 'timetable'
class-attribute
instance-attribute
¶
timeslots = TIMESLOTS
class-attribute
instance-attribute
¶
weekdays = WEEKDAYS
class-attribute
instance-attribute
¶
Timetable
¶
Bases: Resource
A single timetable with start date.
Source code in campus_python/api/v1/timetable.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
entries: Timetables.Timetable.Entries
property
¶
Get the entries resource for this timetable.
metadata: Timetables.Timetable.Metadata
property
¶
Get the metadata resource for this timetable.
attachments: Timetables.Timetable.Attachments
property
¶
Get the attachments resource for this timetable.
Entries
¶
Bases: Resource
Entries for a single timetable.
Source code in campus_python/api/v1/timetable.py
226 227 228 229 230 231 232 233 234 235 | |
list() -> list[campus.model.TimetableEntry]
¶
Return a list of all entries for this timetable.
Source code in campus_python/api/v1/timetable.py
229 230 231 232 233 234 235 | |
Metadata
¶
Bases: Resource
Metadata for a single timetable.
Source code in campus_python/api/v1/timetable.py
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | |
get() -> campus.model.TimetableMetadata
¶
Get the metadata for this timetable.
This does not include timetable entries.
Source code in campus_python/api/v1/timetable.py
240 241 242 243 244 245 246 | |
update(*, label: str | None = None, start_date: str | None = None, end_date: str | None = None) -> campus.model.TimetableMetadata
¶
Update metadata fields for this timetable (subset).
Only the fields explicitly passed change; call with at
least one. label is the committee's display name —
to unset it use clear_label() (the API distinguishes
an absent field from a null one, so this method cannot
express clearing).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str | None
|
The new display name (omit to leave alone). |
None
|
start_date
|
str | None
|
New start date (omit to leave alone). |
None
|
end_date
|
str | None
|
New end date (omit to leave alone). |
None
|
Returns:
| Type | Description |
|---|---|
TimetableMetadata
|
The updated metadata resource. |
Source code in campus_python/api/v1/timetable.py
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | |
clear_label() -> campus.model.TimetableMetadata
¶
Clear the timetable's display label (label = null).
Returns:
| Type | Description |
|---|---|
TimetableMetadata
|
The updated metadata resource. |
Source code in campus_python/api/v1/timetable.py
287 288 289 290 291 292 293 294 | |
Attachments
¶
Bases: Resource
Attachments for a single timetable (files-backed).
Each attachment is a files-backend record under the version's attachments namespace; the committee's original filename rides as the record's display name. Records are plain dicts (the files surface's shape), not campus.model classes.
Source code in campus_python/api/v1/timetable.py
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
list() -> list[dict]
¶
List this timetable's attachments, newest first.
Returns:
| Type | Description |
|---|---|
list[dict]
|
Attachment records (files-backend records); the |
list[dict]
|
attachment id is each record's "id". |
Source code in campus_python/api/v1/timetable.py
306 307 308 309 310 311 312 313 314 | |
upload(data: bytes, filename: str, content_type: str | None = None) -> dict
¶
Attach a file (raw bytes) to this timetable.
Each upload mints a new attachment — re-uploading the same filename adds a second copy (removal is explicit).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
bytes
|
Raw file content (the request body). |
required |
filename
|
str
|
The attachment's display filename (the committee's original filename). |
required |
content_type
|
str | None
|
MIME type to store and serve back (e.g. "application/pdf"); the transport default applies when omitted. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The created attachment record. |
Source code in campus_python/api/v1/timetable.py
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | |
get_content(attachment_id: str) -> bytes
¶
Get an attachment's bytes — the stored version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attachment_id
|
str
|
The attachment id (the record's "id"). |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The content, as stored. |
Source code in campus_python/api/v1/timetable.py
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | |
delete(attachment_id: str) -> None
¶
Remove an attachment (its record and content).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attachment_id
|
str
|
The attachment id to remove. |
required |
Source code in campus_python/api/v1/timetable.py
364 365 366 367 368 369 370 371 | |
delete() -> None
¶
Delete this timetable version and all of its rows (#1088).
DELETE /timetable/
Source code in campus_python/api/v1/timetable.py
205 206 207 208 209 210 211 212 213 214 215 | |
get() -> campus.model.Timetable
¶
Get this timetable (metadata and labeled entries).
GET /timetable/{"timetable": ...} envelope.
Source code in campus_python/api/v1/timetable.py
217 218 219 220 221 222 223 224 | |
__getitem__(timetable_id: str) -> Timetables.Timetable
¶
Get a specific timetable resource by ID.
Source code in campus_python/api/v1/timetable.py
60 61 62 | |
view() -> dict
¶
Get the deployment's timetable pointer state.
Returns:
| Type | Description |
|---|---|
dict
|
{"current": timetable_id | None, "next": timetable_id | |
dict
|
None, "effective_from": datetime | None} — the pending |
dict
|
switch applies at its effective_from without any client |
dict
|
action (#1075). |
Source code in campus_python/api/v1/timetable.py
64 65 66 67 68 69 70 71 72 73 | |
patch(*, current: str | None = None, next: str | None = None, effective_from: str | None = None) -> dict
¶
Patch exactly one timetable pointer (#1075).
Pass keyword arguments, exactly one of current or next.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current
|
str | None
|
Timetable ID to make current, effective now. |
None
|
next
|
str | None
|
Timetable ID to schedule as the pending switch (reschedules any previous pending switch). |
None
|
effective_from
|
str | None
|
When the pending switch applies (ISO
datetime, or YYYY-MM-DD for 07:00 school time). Only
valid with |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The resulting pointer state (same shape as view()). |
Source code in campus_python/api/v1/timetable.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
cancel_next() -> dict
¶
Cancel the pending scheduled switch (API: {next: null}).
Returns:
| Type | Description |
|---|---|
dict
|
The resulting pointer state. |
Source code in campus_python/api/v1/timetable.py
114 115 116 117 118 119 120 | |
me(at: str | None = None) -> dict
¶
Resolve the signed-in user's effective timetable view (#592).
Returns:
| Type | Description |
|---|---|
dict
|
{"current": {timetable_id, lessongroup_id, source}, |
dict
|
"next": null | {..., effective_from, change_type}}; entries |
dict
|
render via timetable[id].entries filtered by |
dict
|
lessongroup_id. |
Source code in campus_python/api/v1/timetable.py
122 123 124 125 126 127 128 129 130 131 132 133 134 | |
new(metadata: dict, data: dict) -> dict
¶
Create a new timetable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata
|
dict
|
Metadata for the timetable (e.g., start_date, end_date) |
required |
data
|
dict
|
Timetable data; must contain the key |
required |
Returns:
| Type | Description |
|---|---|
dict
|
The created timetable resource |
Source code in campus_python/api/v1/timetable.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
list_metadata(**filters: typing.Any) -> list[campus.model.TimetableMetadata]
¶
List timetable metadata records.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**filters
|
Any
|
Arbitrary filter parameters applied to the query. |
{}
|
Returns:
| Type | Description |
|---|---|
list[TimetableMetadata]
|
list[campus.model.TimetableMetadata]: Matching |
list[TimetableMetadata]
|
timetable metadata objects. (GET /timetable/ itself now |
list[TimetableMetadata]
|
serves the pointer state; the list lives at |
list[TimetableMetadata]
|
/timetable/metadata/.) |
Source code in campus_python/api/v1/timetable.py
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | |
ApiRoot¶
campus_python.api.v1.ApiRoot
¶
Bases: ResourceRoot
Campus API resource.
Source code in campus_python/api/v1/__init__.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
url_prefix = '/api/v1'
class-attribute
instance-attribute
¶
assignments: assignments.Assignments
property
¶
Get the assignments resource.
circles: circles.Circles
property
¶
Get the circles resource.
files: files.Files
property
¶
Get the files resource (by-slug + id-based management).
hostedapps: hostedapps.HostedApps
property
¶
Get the hosted-apps resource (by-slug consumer surface).
subjcombi: subjcombi.Subjcombi
property
¶
Get the subjcombi resource (user→lessongroup mappings).
submissions: submissions.Submissions
property
¶
Get the submissions resource.
timetable: timetable.Timetables
property
¶
Get the timetable resource.
__init__(json_client: JsonClient)
¶
Source code in campus_python/api/v1/__init__.py
22 23 24 25 26 27 28 29 30 31 | |