Add direct message and file upload methods to GroupMe SDK #8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "7-add-direct-message-and-file-upload-metho"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds DirectMessagesMixin and FilesMixin to the GroupMe SDK, exposing DM send/list and file upload/status endpoints following the established mixin pattern. File operations target file.groupme.com with a dedicated request handler that shares error-handling semantics with the main API client.
Changes
src/groupme_sdk/direct_messages.py-- new DirectMessagesMixin withsend_dm(recipient_id, text)andlist_chats(page, per_page)src/groupme_sdk/files.py-- new FilesMixin withupload_file(group_id, file_path, content_type)andget_upload_status(group_id, job_id), plus_do_file_requestfor file.groupme.com requestssrc/groupme_sdk/client.py-- added DirectMessagesMixin and FilesMixin to GroupMeClient inheritance chaintests/test_direct_messages.py-- 11 unit tests covering send_dm and list_chatstests/test_files.py-- 12 unit tests covering upload_file and get_upload_statusTest Plan
Review Checklist
Related Notes
Related
Closes #7
QA Review -- PR #8
Pattern Compliance
TYPE_CHECKINGguard,self: GroupMeClientannotation, docstrings with Args/Returns/Raises sections. PASS.file.groupme.comrequests from the mainapi.groupme.combase via_do_file_request. PASS.Issue Found and Fixed
_do_file_request:json,urllib.error, and exception classes were imported inside the method body. The existing pattern inclient.pyuses module-level imports. Fixed in commita3d955a-- moved all imports to module top level.Test Coverage
Ruff
ruff format-- cleanruff check-- cleanVERDICT: APPROVED
PR #8 Review
DOMAIN REVIEW
Tech stack: Pure Python SDK (stdlib only: urllib, json, mimetypes, os, uuid). No frameworks. Mixin inheritance pattern for composing
GroupMeClient.Pattern conformance: Both new mixins (
DirectMessagesMixin,FilesMixin) follow the established mixin pattern exactly:from __future__ import annotations+TYPE_CHECKINGguard for circular import avoidanceself: GroupMeClientannotation on every method_request()for standard API endpoints and a new_do_file_request()for the file.groupme.com domainDRY analysis:
_do_file_request(files.py lines 100-112) mirrors the error-handling logic from_request(client.py lines 65-78). This is intentional -- the response parsing differs (_requestunwraps a{"response": ...}envelope;_do_file_requestreturns raw JSON because file.groupme.com does not use the envelope). The error-handling duplication (HTTPError/URLError mapping) is in the HTTP transport layer, not the auth path. Token injection happens per-method viaself.token, which is the same single-source pattern used everywhere. Acceptable tradeoff for a 12-line private method. If the file API grows beyond 2-3 methods, extracting a shared_handle_http_errorshelper would be warranted.PEP compliance: PEP 8 naming, PEP 484 type hints on all signatures, PEP 257 docstrings present on every public method and class. Line length within the 120 configured in ruff.
Input validation:
upload_filevalidatesfile_pathexistence viaos.path.isfile()before any I/O -- good. String parameters (group_id,recipient_id,job_id) are not validated for empty/None, but this is consistent with every existing mixin in the codebase (groups.py, members.py, messages.py all pass string IDs directly to URL construction). No regression.Error handling: All three exception types (
GroupMeNotFoundError,GroupMeHTTPError,GroupMeError) properly raised withfrom echaining. Empty response body handled (returns{}). Non-list response fromlist_chatshandled (returns[]), matching thelist_groupspattern exactly.Test coverage (23 new tests):
test_direct_messages.py(11 tests): send_dm happy path, source_guid presence, recipient_id in body, correct endpoint URL, 404 error, 500 error. list_chats happy path, pagination params, empty list, non-list defensive return, server error.test_files.py(12 tests): upload correct URL, header validation (token, content-type, filename), auto content-type detection, file data transmission, local FileNotFoundError, 404 error, 500 error. get_upload_status happy path, correct URL, token header, 404 error, network error.mock_file_response(no envelope) for file.groupme.com endpoints and the sharedmock_response(with envelope) for standard API endpoints. This validates the envelope-vs-raw parsing difference.finallyblocks.BLOCKERS
None.
NITS
Memory for large files (
files.pyline 54):file_data = f.read()loads the entire file into memory. For a messaging SDK this is fine in practice, but amax_sizeguard or a note in the docstring about file size limits would be defensive. Non-blocking.Truncated branch name: Branch is
7-add-direct-message-and-file-upload-metho(truncated). Likely Forgejo auto-generation. Cosmetic only.__init__.pyexports: The newDirectMessagesMixinandFilesMixinare not exported in__init__.py. The existing mixins (GroupsMixin,MembersMixin,MessagesMixin) are also not exported -- onlyGroupMeClientand exceptions are. This is consistent. Consumers access methods throughGroupMeClient, not mixins directly. No change needed.Version bump:
pyproject.tomlis still at0.2.0. If this SDK is published to Forgejo PyPI (likepal-e-docs-sdk), a version bump to0.3.0would be needed before publish. This may be handled in a separate chore PR (matching the pattern of PR #6 "chore: bump version to 0.2.0"). Non-blocking for this PR.SOP COMPLIANCE
7-add-direct-message-and-file-upload-methomaps to issue #7)Closes #7) and downstream dependency (groupme-mcp#7)board-westside-basketball)fake-tokenin tests via conftest helper)PROCESS OBSERVATIONS
groupme-mcp#7downstream. Good dependency chain documentation in the PR body.VERDICT: APPROVED