Description
The circle members sub-resource (campus_python/api/v1/circles.py) does not conform to the Campus API for membership mutations. After #41 fixed the nested-path construction, members now resolves to /api/v1/circles/<id>/members, but add()/remove() still hit the wrong endpoints with a wrong payload key, and list() unwraps a response key the API does not send.
Steps to Reproduce
from campus_python import Campus
c = Campus(timeout=10, mode="device")
c.api.circles["circle-1"].members.add("circle-2", 7) # 405
Expected Behavior
Per the Campus API routes (campus-suite, weekly branch, campus/api/routes/circles.py):
GET /api/v1/circles/<id>/members/ — returns the flat {member_id: access_value} mapping directly
POST /api/v1/circles/<id>/members/add — request body {"member_id": ..., "access_value": ...}
DELETE /api/v1/circles/<id>/members/remove — request body {"member_id": ...}
Actual Behavior
add() POSTs to /api/v1/circles/<id>/members with {"member_id": ..., "access": ...} — the trailing-slash redirect lands on /members/ which only allows GET/PATCH (405), and the payload uses "access" where the API expects "access_value"
remove() DELETEs /api/v1/circles/<id>/members — same 405
list() does resp.json()["members"], but the API returns the flat member mapping as the body, so this raises KeyError
Suggested Fix
In CircleMembers:
add(): self.client.post(self.make_path("add"), json={"member_id": member_id, "access_value": access_value})
remove(): self.client.delete(self.make_path("remove"), json={"member_id": member_id})
list(): return resp.json() directly, requesting self.make_path(end_slash=True) to hit the canonical /members/ route
Regression tests for these request targets already exist as a pattern in tests/unit/test_nested_resources.py (see test_members_list_gets_members_endpoint) and should be updated to the corrected endpoints.
Environment
Spun out of #41 ("Out of scope" section).
Description
The circle members sub-resource (
campus_python/api/v1/circles.py) does not conform to the Campus API for membership mutations. After #41 fixed the nested-path construction,membersnow resolves to/api/v1/circles/<id>/members, butadd()/remove()still hit the wrong endpoints with a wrong payload key, andlist()unwraps a response key the API does not send.Steps to Reproduce
Expected Behavior
Per the Campus API routes (campus-suite,
weeklybranch,campus/api/routes/circles.py):GET /api/v1/circles/<id>/members/— returns the flat{member_id: access_value}mapping directlyPOST /api/v1/circles/<id>/members/add— request body{"member_id": ..., "access_value": ...}DELETE /api/v1/circles/<id>/members/remove— request body{"member_id": ...}Actual Behavior
add()POSTs to/api/v1/circles/<id>/memberswith{"member_id": ..., "access": ...}— the trailing-slash redirect lands on/members/which only allows GET/PATCH (405), and the payload uses"access"where the API expects"access_value"remove()DELETEs/api/v1/circles/<id>/members— same 405list()doesresp.json()["members"], but the API returns the flat member mapping as the body, so this raisesKeyErrorSuggested Fix
In
CircleMembers:add():self.client.post(self.make_path("add"), json={"member_id": member_id, "access_value": access_value})remove():self.client.delete(self.make_path("remove"), json={"member_id": member_id})list(): returnresp.json()directly, requestingself.make_path(end_slash=True)to hit the canonical/members/routeRegression tests for these request targets already exist as a pattern in
tests/unit/test_nested_resources.py(seetest_members_list_gets_members_endpoint) and should be updated to the corrected endpoints.Environment
main@ d76e8be (post-Fix nested resources dropping their path part (405 on responses/feedback/links/entries/metadata/members) #41)weeklybranch routesSpun out of #41 ("Out of scope" section).