Skip to content

feat: Python SDK update for version 19.0.0#143

Open
ArnabChatterjee20k wants to merge 3 commits into
mainfrom
dev
Open

feat: Python SDK update for version 19.0.0#143
ArnabChatterjee20k wants to merge 3 commits into
mainfrom
dev

Conversation

@ArnabChatterjee20k
Copy link
Copy Markdown
Member

@ArnabChatterjee20k ArnabChatterjee20k commented May 18, 2026

This PR contains updates to the Python SDK for version 19.0.0.

What's Changed

  • Breaking: Renamed AuthMethod enum to ProjectAuthMethodId
  • Breaking: Renamed EmailTemplateType to ProjectEmailTemplateId and EmailTemplateLocale to ProjectEmailTemplateLocale
  • Breaking: Renamed ServiceId to ProjectServiceId, ProtocolId to ProjectProtocolId, Secure to ProjectSMTPSecure, ProjectPolicy to ProjectPolicyId
  • Breaking: Replaced Scopes enum with ProjectKeyScopes for project key endpoints
  • Breaking: Removed update_deny_canonical_email_policy; replaced with update_deny_aliased_email_policy, update_deny_disposable_email_policy, and update_deny_free_email_policy
  • Breaking: Removed AuthProvider model; use new ProjectOAuthProviderId enum instead
  • Added: Project.get method to fetch current project details
  • Added: Advisor, Presences, and Usage services
  • Added: Insight, Presence, Report, UsageEvent, and UsageGauge models with list variants
  • Added: ProjectAuthMethod, ProjectProtocol, and ProjectService models
  • Added: ProjectOAuthProviderId and ProjectOAuth2GooglePrompt enums
  • Updated: Project, Database, and OAuth2Google model schemas
  • Updated: X-Appwrite-Response-Format header to 1.9.5

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 18, 2026

Greptile Summary

This PR updates the Python SDK to version 19.0.0, introducing three new services (Advisor, Presences, Usage), refactoring the Project model to structured sub-objects, renaming a family of enums, and fixing Document/Row.with_data to use explicit allowlists instead of $-prefix heuristics.

  • New services and models: Advisor (reports/insights), Presences (presence logs with generic typed metadata), and Usage (events/gauges) are fully implemented with Pydantic models and corresponding tests.
  • Project model overhaul: Flat boolean fields for auth methods, services, and protocols are replaced by typed sub-object lists (ProjectAuthMethod, ProjectService, ProjectProtocol), and the Project.get() endpoint is newly exposed.
  • Breaking enum renames: AuthMethod, ServiceId, ProtocolId, Secure, etc. are replaced by ProjectAuthMethodId, ProjectServiceId, ProjectProtocolId, ProjectSMTPSecure, and so on; a new ProjectKeyScopes and ProjectOAuthProviderId enum are added.

Confidence Score: 4/5

The core SDK logic is sound, but three presence service tests (test_get, test_upsert, test_update_presence) will fail in CI because their fixture dicts do not include the 'metadata': {} key that Presence.to_dict() unconditionally injects.

All new service logic (Advisor, Usage, Presences) is correctly implemented and the pre-existing with_data bug was fixed. However, the three new presence test assertions compare against fixtures that lack 'metadata': {}, which Presence.to_dict() always appends — the same way database tests explicitly add data['data'] = {} before asserting. Those tests will not pass as written. The open item about OAuth2GooglePrompt / ProjectOAuth2GooglePrompt duplication is a design concern but does not affect runtime behavior.

test/services/test_presences.py — the three single-presence test assertions need data['metadata'] = {} added before the assertEqual call, mirroring the pattern used in test_databases.py.

Important Files Changed

Filename Overview
appwrite/services/presences.py New Presences service with correct with_data fix (explicit internal_aliases set); test assertions for test_get/upsert/update_presence will fail due to metadata:{} injection discussed in prior thread
appwrite/services/advisor.py New Advisor service; clean implementation of list_reports, get_report, delete_report, list_insights, get_insight with correct model hydration
appwrite/services/usage.py New Usage service with list_events and list_gauges; straightforward implementation with correct model hydration
appwrite/services/project.py Adds Project.get(), three new update_deny_* methods, and update_o_auth2_google prompt parameter; enum references updated throughout; ProjectOAuthProviderId includes GITHUBIMAGINE/GOOGLEIMAGINE/YAMMER but these were already missing from the dispatch table in the base branch
appwrite/models/presence.py Presence generic model with fixed with_data using explicit internal_aliases; to_dict always injects metadata:{} (intentional per dev, consistent with Document); test fixture mismatch is a known open item
appwrite/models/o_auth2_google.py Adds prompt field typed as List[OAuth2GooglePrompt], while update_o_auth2_google accepts List[ProjectOAuth2GooglePrompt] — type inconsistency between model and service noted in prior thread
appwrite/models/project.py Refactored Project model replacing flat auth/service/protocol booleans with typed sub-object lists (ProjectAuthMethod, ProjectService, ProjectProtocol)
appwrite/models/document.py with_data updated to use explicit internal_aliases allowlist and support nested data key; behavioral change for documents with a user field named 'data' is intentional for v19
appwrite/encoders/value_class_encoder.py Imports and isinstance checks updated for renamed enums; new OAuth2GooglePrompt added alongside ProjectOAuth2GooglePrompt
appwrite/models/insight.py New Insight model with all required fields including parentResourceType/parentResourceId (empty string when no parent) and optional analyzed/dismissed fields
appwrite/models/presence_list.py PresenceList.with_data correctly replaces Pydantic-parsed presences with metadata-typed instances; to_dict() (inherited) won't propagate _metadata for nested items, consistent with DocumentList behavior

Reviews (3): Last reviewed commit: "chore: update Python SDK to 19.0.0" | Re-trigger Greptile

Comment thread appwrite/models/presence.py
Comment on lines +1 to +6
from enum import Enum

class OAuth2GooglePrompt(Enum):
NONE = "none"
CONSENT = "consent"
SELECT_ACCOUNT = "select_account"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Duplicate enum with ProjectOAuth2GooglePrompt

OAuth2GooglePrompt (this file) and ProjectOAuth2GooglePrompt (appwrite/enums/project_o_auth2_google_prompt.py) define the exact same three values (none, consent, select_account). Both are imported and registered in value_class_encoder.py. The encoder handles OAuth2GooglePrompt but no service or model appears to accept it as a parameter — only ProjectOAuth2GooglePrompt is used in project.py. If OAuth2GooglePrompt is a legacy shim it should be marked deprecated; if it is truly redundant it should be removed.

Comment thread appwrite/services/advisor.py Outdated
Comment on lines +63 to +72
def to_dict(self) -> Dict[str, Any]:
result = super().to_dict()
if hasattr(self, '_metadata'):
if isinstance(self._metadata, dict):
result['metadata'] = self._metadata
elif hasattr(self._metadata, 'model_dump'):
result['metadata'] = self._metadata.model_dump(mode='json')
else:
result['metadata'] = self._metadata
return result
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 to_dict() always injects metadata: {} into the output

_metadata is initialized via PrivateAttr(default_factory=dict), so hasattr(self, '_metadata') is always True and isinstance({}, dict) is always True. Every call to to_dict() will therefore add "metadata": {} to the result — even when no user-defined metadata was ever set. The three test assertions in test_presences.py (test_get, test_upsert, test_update_presence) all compare response.to_dict() against fixtures that have no "metadata" key, so all three tests will fail at runtime.

Suggested change
def to_dict(self) -> Dict[str, Any]:
result = super().to_dict()
if hasattr(self, '_metadata'):
if isinstance(self._metadata, dict):
result['metadata'] = self._metadata
elif hasattr(self._metadata, 'model_dump'):
result['metadata'] = self._metadata.model_dump(mode='json')
else:
result['metadata'] = self._metadata
return result
def to_dict(self) -> Dict[str, Any]:
result = super().to_dict()
if hasattr(self, '_metadata') and self._metadata:
if isinstance(self._metadata, dict):
result['metadata'] = self._metadata
elif hasattr(self._metadata, 'model_dump'):
result['metadata'] = self._metadata.model_dump(mode='json')
else:
result['metadata'] = self._metadata
return result

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant