Skip to content

Commit 58c51a8

Browse files
tpellissierclaude
andcommitted
Update docs and examples to show context manager usage
- README: Quick Start uses `with` block, add Context Manager to key concepts - SKILL.md (both copies): show `with` pattern as recommended - walkthrough.py: extract body to _run_walkthrough(), wrap in `with` - relationships.py: extract body to _run_example(), wrap in `with` - file_upload.py: add client.close() at end (module-level script) - installation_example.py: use `with` in interactive test and docstring Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a6d3f56 commit 58c51a8

File tree

7 files changed

+58
-37
lines changed

7 files changed

+58
-37
lines changed

.claude/skills/dataverse-sdk-use/SKILL.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@ credential = AzureCliCredential()
5353
credential = ClientSecretCredential(tenant_id, client_id, client_secret)
5454
credential = CertificateCredential(tenant_id, client_id, cert_path)
5555

56-
# Create client (no trailing slash on URL!)
56+
# Create client with context manager (recommended -- enables HTTP connection pooling)
57+
# No trailing slash on URL!
58+
with DataverseClient("https://yourorg.crm.dynamics.com", credential) as client:
59+
... # all operations here
60+
# Session closed, caches cleared automatically
61+
62+
# Or without context manager:
5763
client = DataverseClient("https://yourorg.crm.dynamics.com", credential)
5864
```
5965

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ The SDK provides a simple, pythonic interface for Dataverse operations:
113113
| Concept | Description |
114114
|---------|-------------|
115115
| **DataverseClient** | Main entry point; provides `records`, `query`, `tables`, and `files` namespaces |
116+
| **Context Manager** | Use `with DataverseClient(...) as client:` for automatic cleanup and HTTP connection pooling |
116117
| **Namespaces** | Operations are organized into `client.records` (CRUD & OData queries), `client.query` (query & search), `client.tables` (metadata), and `client.files` (file uploads) |
117118
| **Records** | Dataverse records represented as Python dictionaries with column schema names |
118119
| **Schema names** | Use table schema names (`"account"`, `"new_MyTestTable"`) and column schema names (`"name"`, `"new_MyTestColumn"`). See: [Table definitions in Microsoft Dataverse](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/entity-metadata) |
@@ -131,17 +132,18 @@ from PowerPlatform.Dataverse.client import DataverseClient
131132

132133
# Connect to Dataverse
133134
credential = InteractiveBrowserCredential()
134-
client = DataverseClient("https://yourorg.crm.dynamics.com", credential)
135135

136-
# Create a contact
137-
contact_id = client.records.create("contact", {"firstname": "John", "lastname": "Doe"})
136+
with DataverseClient("https://yourorg.crm.dynamics.com", credential) as client:
137+
# Create a contact
138+
contact_id = client.records.create("contact", {"firstname": "John", "lastname": "Doe"})
138139

139-
# Read the contact back
140-
contact = client.records.get("contact", contact_id, select=["firstname", "lastname"])
141-
print(f"Created: {contact['firstname']} {contact['lastname']}")
140+
# Read the contact back
141+
contact = client.records.get("contact", contact_id, select=["firstname", "lastname"])
142+
print(f"Created: {contact['firstname']} {contact['lastname']}")
142143

143-
# Clean up
144-
client.records.delete("contact", contact_id)
144+
# Clean up
145+
client.records.delete("contact", contact_id)
146+
# Session closed, caches cleared automatically
145147
```
146148

147149
### Basic CRUD operations

examples/advanced/file_upload.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,4 +375,5 @@ def get_dataset_info(file_path: Path):
375375
except Exception as e: # noqa: BLE001
376376
print({"test_file_8mb_deleted": False, "error": str(e)})
377377

378+
client.close()
378379
print("Done.")

examples/advanced/relationships.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,6 @@ def backoff(op, *, delays=(0, 2, 5, 10, 20, 20)):
109109

110110

111111
def main():
112-
# Initialize relationship IDs to None for cleanup safety
113-
rel_id_1 = None
114-
rel_id_2 = None
115-
rel_id_3 = None
116-
117112
print("=" * 80)
118113
print("Dataverse SDK - Relationship Management Example")
119114
print("=" * 80)
@@ -136,8 +131,16 @@ def main():
136131
credential = InteractiveBrowserCredential()
137132

138133
log_call(f"DataverseClient(base_url='{base_url}', credential=...)")
139-
client = DataverseClient(base_url=base_url, credential=credential)
140-
print(f"[OK] Connected to: {base_url}")
134+
with DataverseClient(base_url=base_url, credential=credential) as client:
135+
print(f"[OK] Connected to: {base_url}")
136+
_run_example(client)
137+
138+
139+
def _run_example(client):
140+
# Initialize relationship IDs to None for cleanup safety
141+
rel_id_1 = None
142+
rel_id_2 = None
143+
rel_id_3 = None
141144

142145
# ============================================================================
143146
# 2. CLEANUP PREVIOUS RUN (Idempotency)

examples/advanced/walkthrough.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,12 @@ def main():
8787
credential = InteractiveBrowserCredential()
8888

8989
log_call(f"DataverseClient(base_url='{base_url}', credential=...)")
90-
client = DataverseClient(base_url=base_url, credential=credential)
91-
print(f"[OK] Connected to: {base_url}")
90+
with DataverseClient(base_url=base_url, credential=credential) as client:
91+
print(f"[OK] Connected to: {base_url}")
92+
_run_walkthrough(client)
9293

94+
95+
def _run_walkthrough(client):
9396
# ============================================================================
9497
# 2. TABLE CREATION (METADATA)
9598
# ============================================================================

examples/basic/installation_example.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,12 @@ def show_usage_examples():
205205
# Set up authentication
206206
credential = InteractiveBrowserCredential()
207207
208-
# Create client
209-
client = DataverseClient(
210-
"https://yourorg.crm.dynamics.com",
211-
credential
212-
)
208+
# Recommended: use context manager for connection pooling and automatic cleanup
209+
with DataverseClient("https://yourorg.crm.dynamics.com", credential) as client:
210+
... # all operations here
211+
212+
# Or without context manager:
213+
client = DataverseClient("https://yourorg.crm.dynamics.com", credential)
213214
```
214215
215216
CRUD Operations:
@@ -307,19 +308,18 @@ def interactive_test():
307308
credential = InteractiveBrowserCredential()
308309

309310
print(" Creating client...")
310-
client = DataverseClient(org_url.rstrip("/"), credential)
311-
312-
print(" Testing connection...")
313-
tables = client.tables.list()
314-
print(f" [OK] Connection successful!")
315-
print(f" Found {len(tables)} tables in environment")
316-
317-
custom_tables = client.tables.list(
318-
filter="IsCustomEntity eq true",
319-
select=["LogicalName", "SchemaName"],
320-
)
321-
print(f" Found {len(custom_tables)} custom tables (filter + select)")
322-
print(f" Connected to: {org_url}")
311+
with DataverseClient(org_url.rstrip("/"), credential) as client:
312+
print(" Testing connection...")
313+
tables = client.tables.list()
314+
print(f" [OK] Connection successful!")
315+
print(f" Found {len(tables)} tables in environment")
316+
317+
custom_tables = client.tables.list(
318+
filter="IsCustomEntity eq true",
319+
select=["LogicalName", "SchemaName"],
320+
)
321+
print(f" Found {len(custom_tables)} custom tables (filter + select)")
322+
print(f" Connected to: {org_url}")
323323

324324
print("\n Your SDK is ready for use!")
325325
print(" Check the usage examples above for common patterns")

src/PowerPlatform/Dataverse/claude_skill/dataverse-sdk-use/SKILL.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@ credential = AzureCliCredential()
5353
credential = ClientSecretCredential(tenant_id, client_id, client_secret)
5454
credential = CertificateCredential(tenant_id, client_id, cert_path)
5555

56-
# Create client (no trailing slash on URL!)
56+
# Create client with context manager (recommended -- enables HTTP connection pooling)
57+
# No trailing slash on URL!
58+
with DataverseClient("https://yourorg.crm.dynamics.com", credential) as client:
59+
... # all operations here
60+
# Session closed, caches cleared automatically
61+
62+
# Or without context manager:
5763
client = DataverseClient("https://yourorg.crm.dynamics.com", credential)
5864
```
5965

0 commit comments

Comments
 (0)