Releases: microsoft/PowerPlatform-DataverseClient-Python
Releases · microsoft/PowerPlatform-DataverseClient-Python
v1.0.0
Breaking Changes
-
Previously deprecated flat methods on
DataverseClient(create,update,delete,get,list,query_sql,upload_file, etc.) are now removed; use the namespaced operations:client.records,client.query,client.tables,client.files,client.batch(#175) -
client.query.sql_select(),client.query.sql_joins(),client.query.sql_join()are removed (#175) -
QueryBuilder.execute()now returns a flatQueryResultinstead ofIterable[Record]; useexecute_pages()for lazy iteration (#175)Run
dataverse-migrate --dry-run .to automatically rewrite v0 call sites (pip install PowerPlatform-Dataverse-Client[migration]).
Added
- Async client —
AsyncDataverseClientwith full feature parity to the sync SDK; all operation namespaces available withasync withlifecycle management. Install withpip install PowerPlatform-Dataverse-Client[async](#171) - Single-record fetch —
client.records.retrieve(table, record_id, *, select, expand, include_annotations)returnsNoneon 404 instead of raising;expandadds$expandfor navigation-property expansion on the single-record GET;include_annotationsmaps to thePrefer: odata.include-annotationsheader for formatted values and lookup labels (#175) - Multi-record fetch —
client.records.list(table, *, filter, select, top, orderby, expand, page_size, count, include_annotations)returns an eager flatQueryResult; GA replacement forrecords.get()without a record ID;page_sizecontrolsPrefer: odata.maxpagesize,count=Trueadds$count=true,include_annotationsrequests formatted values (#175) - Streaming multi-record fetch —
client.records.list_pages(...)yields oneQueryResultper HTTP page; streaming counterpart tolist()with the same parameter set (#175) - FetchXML —
client.query.fetchxml(xml)returns an inertFetchXmlQuery; no HTTP call until.execute()or.execute_pages(). Paging implements the documented Dataverse algorithm: annotation parsed as outer XML,pagingcookieattribute double URL-decoded, server-suppliedpagenumberused for the next page,morerecordshandled as bothbooland"true"string,UserWarningemitted on simple-paging fallback, 32,768-character URL limit enforced (documented Dataverse GET cap), 10,000-page circuit breaker against runaway iteration (#175) - Streaming QueryBuilder —
QueryBuilder.execute_pages()lazily yields oneQueryResultper HTTP page; replaces deprecatedexecute(by_page=True)(#175) - Composable filters —
QueryBuilder.where(col("name") == "Contoso")with Python operators (==,>,&,|,~); replaces the deprecatedfilter_eq(),filter_contains(), and otherfilter_*helpers (#175) QueryResultindexing —result[0]returns aRecord;result[1:5]returns a newQueryResult(#175)DataverseModelprotocol — structuralProtocolinmodels/protocol.pyfor typed entity classes; enables CRUD operations without manual table names or dict serialization (#175)- Top-level re-exports —
col(),raw(),QueryResult, andDataverseModelimportable directly from the top-levelPowerPlatform.Dataversepackage (#175) - Shorter imports — public types (
Record,DataverseError,QueryBuilder,BatchResult, and others) now importable directly fromPowerPlatform.Dataverse.models,.core, and.operations(#165) - Migration tool — installed as the
dataverse-migrateconsole script (also runnable viapython -m PowerPlatform.Dataverse.migration.migrate_v0_to_v1); rewrites v0 call sites to the v1 API with--dry-runsupport; coverscreate,update,delete,get,list,fetchxml, and query-builder patterns; emits a[NEEDS-MANUAL]label for files with no auto-rewrites but manual attention needed, and appends a trailing note on[MIGRATED]lines when manual items remain. Requires the[migration]optional extra (pip install PowerPlatform-Dataverse-Client[migration]) (#175)
Changed
records.get()deprecation extended: calling with arecord_idemitsDeprecationWarningdirecting callers toretrieve(); calling without arecord_iddirects callers tolist()(#175)OperationContextnow validates keys and values against an allowlist; unknown keys or non-conforming values raiseValidationError, preventing PII from reaching theUser-Agentheader (#181)- Table creation now uses the
CreateEntitiesAPI, improving performance (#183) float/doublecolumn precision default raised from 2 to 5 decimal places, preventing silent truncation of values like2.718(#185)- Server inner error messages now surface in
HttpError.messageon both single-request and batch paths (#185) pandas.DataFramewith MultiIndex columns now raises a descriptive error with a flatten hint instead of failing deep in serialization (#185)
Fixed
- Client creation no longer errors on Python 3.10 and 3.11 (#188)
- SQL guardrails now catch write statements hidden inside comments, string literals, or zero-width prefixes (#185)
Deprecated
QueryBuilder.execute(by_page=True)andexecute(by_page=False)emitUserWarning; useexecute_pages()andexecute()respectively (#175)client.query.odata_select(),client.query.odata_expands(),client.query.odata_expand(),client.query.odata_bind()emitDeprecationWarning; navigation-property helpers are replaced byQueryBuilder.expand()(#175)
v0.1.0b10
Added
DataverseClient(context=OperationContext(...))keyword argument (also settable viaDataverseConfig(operation_context=...)) that appends a parenthesized comment to the outboundUser-Agentheader so callers can attribute their traffic in Dataverse server logs — e.g.DataverseSvcPythonClient:0.1.0b10 (app=dataverse-skills/1.2.1)(#178)
v0.1.0b9
Added
client.dataframe.sql(): execute a SQL SELECT and get results directly as a pandas DataFrame (#141)- Schema discovery:
client.query.list_columns(),client.query.list_relationships(), andclient.query.list_table_relationships()to inspect table columns and relationships from metadata (#141) - SQL query helpers:
client.query.sql_columns(),client.query.sql_select(),client.query.sql_joins(), andclient.query.sql_join()to auto-build SQL statements from metadata without knowing column or join syntax manually (#141) - OData query helpers:
client.query.odata_select(),client.query.odata_expands(),client.query.odata_expand(), andclient.query.odata_bind()to auto-discover navigation property names and build@odata.bindvalues from metadata (#141) SELECT *raises aValidationErrorwith a clear message instead of sending the query to the server, which does not support wildcard selects; useclient.query.sql_columns()to discover available columns (#141)- SQL safety guardrails: write statements (
INSERT,UPDATE,DELETE, etc.) raiseValidationErrorbefore hitting the server; cartesian joins (FROM a, b) and leading-wildcardLIKEpatterns emitUserWarning(#141) client.tables.create()now accepts an optionaldisplay_nameparameter to set a human-readable label for the table in Dataverse; defaults to the schema name when omitted (#164)- Opt-in HTTP diagnostics logging: pass a
LogConfigtoDataverseConfigto log all HTTP request and response traffic to rotating local log files with automatic redaction of sensitive headers (Authorization, etc.) (#135)
Changed
client.tables.create_lookup_field()now automatically lowercasesreferencing_tableandreferenced_tableto valid Dataverse logical names; callers no longer need to call.lower()manually (#141)
v0.1.0b8
Added
- Batch API:
client.batchnamespace for deferred-execution batch operations that pack multiple Dataverse Web API calls into a singlePOST $batchHTTP request (#129) - Batch DataFrame integration:
client.batch.dataframenamespace with pandas DataFrame wrappers for batch operations (#129) client.records.upsert()andclient.batch.records.upsert()backed by theUpsertMultiplebound action with alternate-key support (#129)- QueryBuilder:
client.query.builder("table")with a fluent API, 20+ chainable methods (select,filter_eq,filter_contains,order_by,expand, etc.), and composable filter expressions using Python operators (&,|,~) (#118) - Memo/multiline column type support:
"memo"(or"multiline") can now be passed as a column type inclient.tables.create()andclient.tables.add_columns()(#155)
Changed
- Picklist label-to-integer resolution now uses a single bulk
PicklistAttributeMetadataAPI call for the entire table instead of per-attribute requests, with a 1-hour TTL cache (#154)
Fixed
client.query.sql()silently truncated results at 5,000 rows. The method now follows@odata.nextLinkpagination and returns all matching rows (#157)- Alternate key fields were incorrectly merged into the
UpsertMultiplerequest body, causing400 Bad Requeston the create path (#129) - Docstring type annotations corrected for Microsoft Learn API reference compatibility (#153)
v0.1.0b7
Added
- DataFrame namespace:
client.dataframe.get(),.create(),.update(),.delete()for working with Dataverse records as pandas DataFrames and Series — no manual dict conversion required (#98) - Table metadata now includes
primary_name_attributeandprimary_id_attributefromtables.create()andtables.get_info()(#148)
Changed
pandas>=2.0.0is now a required dependency (#98)
v0.1.0b6
Added
- Context manager support:
with DataverseClient(...) as client:for automatic resource cleanup, HTTP connection pooling, andclose()for explicit lifecycle management (#117) - Typed return models
Record,TableInfo, andColumnInfofor record and table metadata operations, replacing rawDict[str, Any]returns with full backward compatibility (result["key"]still works) (#115) - Alternate key management:
client.tables.create_alternate_key(),client.tables.get_alternate_keys(),client.tables.delete_alternate_key()with typedAlternateKeyInfomodel (#126)
Fixed
@odata.bindlookup bindings now preserve navigation property casing (e.g.,new_CustomerId@odata.bind), fixing400 Bad Requesterrors on create/update/upsert with lookup fields (#137)- Reduced unnecessary HTTP round-trips on create/update/upsert when records contain
@odata.bindkeys (#137) - Single-record
get()now lowercases$selectcolumn names consistently with multi-record queries (#137)
v0.1.0b5
Fixed
- UpsertMultiple: exclude alternate key fields from request body (#127). The create path of UpsertMultiple failed with
400 Bad Requestwhen alternate key column values appeared in both the body and@odata.id.
Full Changelog: v0.1.0b4...v0.1.0b5
v0.1.0b4
Added
- Operation namespaces:
client.records,client.query,client.tables,client.files(#102) - Relationship management:
create_one_to_many_relationship,create_many_to_many_relationship,get_relationship,delete_relationship,create_lookup_fieldwith typedRelationshipInforeturn model (#105, #114) client.records.upsert()for upsert operations with alternate key support (#106)client.files.upload()for file upload operations (#111)client.tables.list(filter=, select=)parameters for filtering and projecting table metadata (#112)- Cascade behavior constants (
CASCADE_BEHAVIOR_CASCADE,CASCADE_BEHAVIOR_REMOVE_LINK, etc.) and input models (CascadeConfiguration,LookupAttributeMetadata,Label,LocalizedLabel)
Deprecated
- All flat methods on
DataverseClient(create,update,delete,get,query_sql,upload_file, etc.) now emitDeprecationWarningand delegate to the corresponding namespaced operations
Full Changelog: v0.1.0b3...v0.1.0b4