Skip to content

Conversation

@tpellissier-msft
Copy link
Collaborator

Summary

  • Implements Phase 1 of SDK restructure: fluent .with_response_details() API pattern for optional telemetry access
  • All CRUD methods now return OperationResult wrapper with transparent dunder delegation (__iter__, __getitem__, __len__, etc.)
  • Adds RequestTelemetryData and DataverseResponse result types for standardized telemetry access
  • Extends telemetry support to paginated get() queries with per-page telemetry access

Changes

New module: core/results.py

  • RequestTelemetryData: Immutable dataclass capturing correlation IDs from HTTP requests
  • DataverseResponse[T]: Standard response object with result and telemetry properties
  • OperationResult[T]: Wrapper enabling fluent .with_response_details() pattern with transparent delegation

Updated client.py

  • All methods (create, get, update, delete, query_sql, create_table, etc.) return OperationResult
  • Existing code works unchanged via dunder method delegation
  • update() and delete() unwrap OperationResult when passed directly from create()

Updated data/_odata.py

  • Internal _ODataRequestResult type alias for Tuple[Any, RequestTelemetryData]
  • All internal methods now return (result, metadata) tuples
  • Telemetry extracted from response headers (x-ms-service-request-id, x-ms-client-request-id, etc.)

Backward Compatibility

  • ✅ Existing iteration patterns work unchanged: for id in client.create(...)
  • ✅ Indexing works: ids[0]
  • ✅ Length checks work: len(ids)
  • ✅ Equality comparisons work: ids == ["guid-1", "guid-2"]
  • ✅ Batch concatenation works: batch1 + batch2 returns raw list

Usage Examples

# Default behavior (unchanged)
ids = client.create("account", [{"name": "A"}, {"name": "B"}])
for id in ids:
    print(id)

# New: Access telemetry
response = client.create("account", {"name": "Test"}).with_response_details()
print(f"Request ID: {response.telemetry['client_request_id']}")
print(f"Service ID: {response.telemetry['service_request_id']}")

# New: Per-page telemetry for paginated queries
for batch in client.get("account", filter="statecode eq 0"):
    response = batch.with_response_details()
    print(f"Page request ID: {response.telemetry['service_request_id']}")
    for record in batch:
        print(record["name"])

Test plan

  • Unit tests for OperationResult dunder methods (iteration, indexing, equality, bool, contains)
  • Unit tests for DataverseResponse structure
  • Unit tests for batch concatenation (__add__, __radd__)
  • Integration tests for all CRUD methods returning OperationResult
  • Tests for per-page telemetry access in paginated queries
  • Walkthrough example updated with telemetry printing

🤖 Generated with Claude Code

tpellissier and others added 2 commits January 26, 2026 11:13
Phase 1 SDK restructure: All methods return OperationResult with fluent
.with_response_details() API for optional telemetry access.

Changes:
- Add OperationResult wrapper with dunder methods for transparent behavior
- Add RequestTelemetryData and DataverseResponse result types
- Unwrap OperationResult in update/delete to allow operation chaining
- Rename internal type alias to _ODataRequestResult for clarity
- Standardize all _odata.py method return type annotations
- Add telemetry printing to walkthrough example

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extends the fluent .with_response_details() API to support paginated
queries. Each page batch is now wrapped in OperationResult, allowing
telemetry access per page while maintaining backward compatibility.

Changes:
- Add __add__ and __radd__ to OperationResult for batch concatenation
- Modify _get_multiple to yield (batch, metadata) tuples
- Update get() to wrap each page in OperationResult
- Add per-page telemetry printing to walkthrough example
- Add tests for concatenation and per-page telemetry access

Backward compatibility:
- Existing iteration patterns work unchanged via OperationResult delegation
- Batch concatenation (batch1 + batch2) returns raw list as expected

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@tpellissier-msft tpellissier-msft requested a review from a team as a code owner January 26, 2026 22:17
Copilot AI review requested due to automatic review settings January 26, 2026 22:17
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements Phase 1 of an SDK restructure by adding a fluent .with_response_details() API pattern for optional telemetry access. All CRUD methods now return an OperationResult wrapper that provides transparent delegation to the underlying result through dunder methods (__iter__, __getitem__, __len__, etc.), while also enabling explicit telemetry access via .with_response_details().

Changes:

  • Introduces new core/results.py module with RequestTelemetryData, DataverseResponse, and OperationResult types
  • Updates data/_odata.py to return tuples of (result, RequestTelemetryData) from all internal methods
  • Updates client.py to wrap all method results in OperationResult while maintaining backward compatibility
  • Extends telemetry support to paginated queries with per-page telemetry access

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/PowerPlatform/Dataverse/core/results.py New module defining RequestTelemetryData, DataverseResponse, and OperationResult with comprehensive dunder method delegation
src/PowerPlatform/Dataverse/data/_odata.py Updated all internal methods to return (result, RequestTelemetryData) tuples; telemetry extracted from response headers
src/PowerPlatform/Dataverse/client.py All public methods now return OperationResult; added unwrapping logic in update() and delete() for ergonomic chaining
tests/unit/test_results.py Comprehensive unit tests for all result types and dunder method behaviors including iteration, indexing, equality, concatenation
tests/unit/test_client.py Updated client tests to verify OperationResult behavior and telemetry access; added pagination telemetry tests
tests/unit/data/test_logical_crud.py Updated CRUD tests to handle tuple return values with telemetry metadata
examples/advanced/walkthrough.py Enhanced with telemetry printing helper and telemetry access examples throughout all operations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Fix docstring in results.py: RequestMetadata -> RequestTelemetryData
- Move Tuple import to top of _odata.py with other typing imports

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Update internal _request() call sites to unpack (response, telemetry)
tuples after Phase 1 changes. Also use duck typing instead of
isinstance(x, list) for OperationResult compatibility.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

3 participants