Skip to content

Comuna-prog/ms-graph-python-helpers

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ms-graph-python-helpers

Small, testable helpers around the Microsoft Graph HTTP API. These are the pieces I write every time I hook a Python service into a Microsoft 365 tenant. The official SDKs cover the wire protocol; these helpers cover the awkward corners the SDK leaves to you.

What it solves

  • Fuzzy contact lookup. Business users write names, not object IDs. Given "felipe delgado", find the right Graph user even if the display name in the tenant is "Juan Felipe Delgado Quevedo".
  • SharePoint uploads that survive real files. Wraps Microsoft's upload session protocol so files above the simple-upload limit go through cleanly. Retries on transient chunk failures, resumable.
  • Paginated iteration made honest. Graph pages with @odata.nextLink. A helper iterator that yields entities one by one so you can process 50k transcripts without loading them all into memory.
  • Bot Framework image ingestion. Downloads attachments from a Teams message with the right bearer token, saves them with a real extension based on content-type, and skips files above a configurable size cap.

Every helper takes an HTTP client as a Protocol so you can inject a fake in tests. Nothing here talks to the network by itself.

What it is not

  • Not a full Microsoft Graph SDK. Use msgraph-sdk or msal for authentication and full API coverage.
  • Not opinionated about auth. You pass in an already-authenticated HTTP client. Client credentials, device code, or delegated OAuth all work.

Requirements

  • Python 3.11 or later.
  • httpx for the example clients (helpers themselves accept any client that matches the HttpClient Protocol).
pip install -e .

Quick start

from ms_graph_helpers import GraphClient, ContactFinder

graph = GraphClient(http_client=my_authenticated_httpx_client, base_url="https://graph.microsoft.com/v1.0")
finder = ContactFinder(graph)

user = finder.find("felipe delgado")
if user is None:
    raise ValueError("No confident match")
print(user["id"], user["displayName"], user["userPrincipalName"])

Helpers

Helper File Purpose
GraphClient client.py Thin wrapper around any authenticated HTTP client with retries and pagination.
ContactFinder contacts.py Accent- and case-insensitive fuzzy matcher against /users. Returns a single best match or None when the confidence gap is too small.
SharePointUploader sharepoint.py Upload files through createUploadSession. Chunked, resumable, streams from disk.
TranscriptIterator transcripts.py Iterates Teams call transcripts across pages with a since filter for delta polling.
BotAttachmentDownloader bot_attachments.py Downloads Bot Framework image attachments, resolves the real extension from content-type, enforces a size cap.

Design decisions

  • HTTP client is injected. No SDK dependency. Tests use a scripted fake client. Production uses httpx.Client or requests.Session, whichever your app already carries.
  • Pagination is a generator. TranscriptIterator yields one entity at a time. Callers decide when to stop. This is how you process a tenant's worth of transcripts without OOMing.
  • Contact fuzzy match returns None on tie. If two users match with similar scores, no result is returned. Better to raise for a human than to silently pick the wrong Juan.
  • Attachment extension mapping is explicit. content-type: image/jpeg maps to .jpg. Never .bin. The mapping is a table, not a call to mimetypes.guess_extension() which is unreliable with the extended content types Bot Framework attaches.

Gotchas from real use

  • Bot Framework attachment tokens have short expiration. Download the file the moment you receive the message, don't queue the URL for later.
  • createUploadSession requires the site drive item path to already exist. If a folder needs to be created, use the drive item creation endpoint before starting the session.
  • /users returns paginated results even when there's only one match. The default page size is small; use $top=999 for lookups when you know the tenant is not enormous.

Tests

pytest tests/

Tests use a scripted FakeHttpClient and cover: fuzzy match tie-breaking, pagination termination, attachment extension resolution, and upload session error surfacing.

License

MIT. See LICENSE.

About

Small, testable Python helpers around the Microsoft Graph HTTP API. Fuzzy contacts, chunked SharePoint uploads, paginated transcripts, Bot Framework attachments.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages