feat: SDK-native column constraints (create, update, typed read) — Layer 1 of cutting raw-urllib usage - #206
Open
arorashivam96 wants to merge 6 commits into
Open
arorashivam96 wants to merge 6 commits into
arorashivam96 wants to merge 6 commits into
Conversation
…reate/add_columns
tables.create/add_columns previously accepted only a type string (or Enum) per column, so MaxLength, MinValue/MaxValue, Precision, Format, RequiredLevel, and a custom DisplayName could not be set - callers had to drop to the raw EntityDefinitions/Attributes Web API. A column-spec value may now also be a dict pairing a base type with overrides, e.g. {'type': 'int', 'min_value': 1, 'max_value': 5} or {'type': 'memo', 'max_length': 2000, 'display_name': 'Comment'}. str/Enum specs are unchanged (backward-compatible).
_attribute_payload now extracts overrides from a dict spec, builds the base payload via _base_attribute_payload, then applies the overrides (string/memo format -> FormatName, int/date format -> Format). Unknown keys and a missing 'type' raise ValueError. Adds 10 unit tests; sync+async suites green. Implements #194.
…mn, typed reads + allowlist Folds the full metadata-constraint story into one change so agents never hand-roll the EntityDefinitions/Attributes Web API (the dominant driver of raw-urllib usage in the plugin telemetry): #194 create with constraints: tables.create/add_columns accept a dict column spec {'type','max_length','min_value','max_value','precision','format','required','display_name'}; str/Enum unchanged. #202 tables.update_column/update_columns: update existing column constraints (GET typed attr -> PUT + derived @odata.type, hidden from the caller). #203 typed reads: tables.list_columns(typed=True) and tables.get_column(..., typed=True) via RetrieveMetadataChanges with property projection - one request, no @odata.type URL cast. Allowlist: add dv-overview + erp-xpp to OperationContext._ALLOWED_SKILLS (parity with the plugin auth.py). Sync + async parity; full unit suite green.
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Typed reads silently ignore filters, missing-column errors use the wrong subcode, and async coverage and public documentation are incomplete.
Review effort: Balanced
Findings: 2
Open (4)
What changed in this PR
Adds SDK-native column constraints, typed metadata reads, column updates, and operation-context allowlist parity.
Changes:
- Supports constraint dictionaries when creating columns.
- Adds typed column reads and constraint updates for sync/async clients.
- Allows
dv-overviewanderp-xppoperation contexts.
| File | Description |
|---|---|
tests/unit/test_tables_operations.py |
Updates sync delegation expectations. |
tests/unit/test_operation_context.py |
Tests added skill identifiers. |
tests/unit/data/test_odata_internal.py |
Tests constraints, updates, and typed reads. |
tests/unit/aio/test_async_tables.py |
Updates async delegation expectations. |
src/PowerPlatform/Dataverse/operations/tables.py |
Exposes new sync table APIs. |
src/PowerPlatform/Dataverse/data/_odata.py |
Implements sync typed reads and updates. |
src/PowerPlatform/Dataverse/data/_odata_base.py |
Adds shared constraint handling. |
src/PowerPlatform/Dataverse/core/config.py |
Expands the skill allowlist. |
src/PowerPlatform/Dataverse/aio/operations/async_tables.py |
Exposes async table APIs. |
src/PowerPlatform/Dataverse/aio/data/_async_odata.py |
Implements async typed reads and updates. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… full-definition metadata PUT + MergeLabels, pre-validate update_columns
…t-spec in docstrings + README
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


SDK-native column constraints — Layer 1 of reducing raw-
urllibusageThe problem this fixes
In the Dataverse plugin's telemetry, a large share of traffic is raw
urllib(hand-rolled HTTP) instead of the managed SDK. The single biggest driver is schema metadata on thedv-metadataskill: agents were forced to hand-build calls toEntityDefinitions/Attributesbecause the SDK could not express column constraints. Concretely, three operations had no SDK path:MaxLength,MinValue/MaxValue,Format,RequiredLevel, a customDisplayName).PUT-not-PATCHplus a derived@odata.typediscriminator).@odata.typeURL cast).So for a routine ask like "add a Rating 1–5 and a 2000-char Comment", the agent dropped to raw
urllib, hit the metadata quirks, and looped. This PR gives all three an SDK path, so agents stay on the managed client (which carries auth, retries, and telemetry attribution) and never hand-roll the metadata Web API.What's in this PR
Four changes, all backward-compatible, sync + async parity.
1. Create with constraints (closes #194)
tables.create/add_columnsnow accept a dict column spec alongside the existingstr/Enum:Override keys:
max_length,min_value,max_value,precision,format,required,display_name.2. Update an existing column (closes #202)
New
tables.update_column/update_columns. The SDK reads the typed attribute, applies the overrides, and issues thePUTwith the right@odata.typeinternally — the caller never sees a verb or a discriminator:3. Typed reads in one request (closes #203)
typed=Trueonlist_columns/get_column, backed byRetrieveMetadataChangeswith property projection — type-specific fields come back in a single request, no@odata.typeURL cast:4. Attribution allowlist
Add
dv-overview+erp-xpptoOperationContext._ALLOWED_SKILLS(parity with the plugin'sscripts/auth.py, which allows all 10). Previouslyget_client('dv-overview'|'erp-xpp')raisedValueErroron the SDK side, and the plugin silently fell back to rawurllibfor those two skills.Compatibility
str/Enumcolumn specs and every existing signature are unchanged; the only new parameter is a keyword-onlytyped=Falseonlist_columns. No CHANGELOG / version edit (per CONTRIBUTING — maintainers handle those at release).Testing
Unit — full suite green: 2437 passed (sync + async). New coverage: dict-spec overrides,
update_column(PUT verb +@odata.type+ override application + error paths),RetrieveMetadataChangestyped reads (request shape, projection, criteria),get_column(typed=True), and allowlist parity.Live end-to-end against a Dataverse org (
*.crm10.dynamics.com) — 12/12 checks pass:MinValue=1,MaxValue=5,MaxLength=2000(one request)list_columns(typed=True)returns typed fieldsupdate_columnmemo2000 → 4000, re-read confirmsFor contrast, the unmodified SDK raises
ValueError: Unsupported column spec type ... <class 'dict'>on the very same create — the exact gap this PR closes.