|
| 1 | +# Microsoft Graph Python SDK Upgrade Guide |
| 2 | + |
| 3 | +This guide highlights breaking changes, and new features introduced in the new Microsoft Graph Python SDK. |
| 4 | + |
| 5 | +# Upgrading to msgraph-sdk from msgraph-core |
| 6 | + |
| 7 | +- [Installation](#installation) |
| 8 | +- [New Features](#new-features) |
| 9 | +- [Breaking Changes](#breaking-changes) |
| 10 | + |
| 11 | +# Installation |
| 12 | + |
| 13 | +```py |
| 14 | +# msgraph-core |
| 15 | +pip install msgraph-core |
| 16 | + |
| 17 | +# msgraph-sdk |
| 18 | +pip install msgraph-sdk |
| 19 | +``` |
| 20 | + |
| 21 | +# New Features |
| 22 | + |
| 23 | +## Model classes |
| 24 | + |
| 25 | +The `msgraph-sdk` provides auto-generated model classes that correspond to objects that are accepted and returned from the Microsoft Graph API. These models leverage Python's `typing` features and have fully typed properties, methods and return types. |
| 26 | + |
| 27 | +This package (`msgraph-sdk`) will only contain models that match the [Microsoft Graph v1 API metadata](https://graph.microsoft.com/v1.0/$metadata). If you are interested in the Beta API, please see the [Microsoft Graph Beta Python SDK](https://github.com/microsoftgraph/msgraph-sdk-beta-python). |
| 28 | + |
| 29 | +## Fluent Request Builder Pattern |
| 30 | +`msgraph-sdk` provides a fluent interface that takes advantage of method chaining and IDE autocomplete when making requests to the Graph. This is a shift from `msgraph-core` where raw URLs would be passed instead: |
| 31 | + |
| 32 | +```py |
| 33 | +# msgraph-core |
| 34 | +resp =client.get('/users/userId/messages') |
| 35 | + |
| 36 | +# msgraph-sdk |
| 37 | +req = client.users_by_id('userId').messages().get() |
| 38 | +resp = asyncio.run(req) |
| 39 | +``` |
| 40 | + |
| 41 | +Hopefully this makes it more intuitive to work with the SDK and reduces time checking reference docs. Your feedback would be appreciated on your preferred experience or whether we should support both scenarios. |
| 42 | + |
| 43 | +# Breaking Changes |
| 44 | + |
| 45 | +The following breaking changes were introduced in `msgraph-sdk`: |
| 46 | + |
| 47 | +- [Changes to Authentication Mechanism](#changes-to-authentication) |
| 48 | +- [Changes to the Graph client construction and configuration experience](#changes-to-graph-client-instantiation-and-configuration). |
| 49 | +- [Changes to Graph request functionality](#changes-to-graph-request-functionality). |
| 50 | +- [Dependency changes](#dependency-changes). |
| 51 | + |
| 52 | +## Changes to authentication |
| 53 | +`msgraph-sdk` introduces an `AuthenticationProvider` that handles the fetching, caching and refreshing of tokens ensuring all your requests are always authenticated. |
| 54 | + |
| 55 | +The AuthenticationProvider makes use of the [azure-identity](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity) library hence its name - `AzureIdentityAuthenticationProvider`. The `AzureIdentityAuthenticationProvider` class is imported from the [kiota-authentication](https://github.com/microsoft/kiota-authentication-azure-python) package and expects an async credential. See [azure.identity.aio](https://aka.ms/azsdk/python/identity/aio/docs) documentation for more details on supported credential classes. |
| 56 | + |
| 57 | +```py |
| 58 | + |
| 59 | +# msgraph-core |
| 60 | +from azure.identity import ClientSecretCredential |
| 61 | +from msgraph.core import GraphClient |
| 62 | + |
| 63 | +credential = ClientSecretCredential(tenant_id: str, client_id: str, client_secret: str) |
| 64 | + |
| 65 | + |
| 66 | +# msgraph-sdk |
| 67 | +from azure.identity.aio import ClientSecretCredential # async credentials only |
| 68 | +from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider |
| 69 | + |
| 70 | +credential=ClientSecretCredential(tenant_id: str, client_id: str, client_secret: str) |
| 71 | +auth_provider = AzureIdentityAuthenticationProvider(credential) |
| 72 | +``` |
| 73 | + |
| 74 | +See more [code samples](README.md#create-an-authenticationprovider-object) on how to initialise the Authentication Provider. |
| 75 | + |
| 76 | +## Changes to Graph client instantiation and configuration |
| 77 | + |
| 78 | +`msgraph-sdk` introduces a new format for creating and configuring clients based on our [Kiota](https://github.com/microsoft/kiota) client generator. It involves creating an instance of a `GraphRequestAdapter` that will take care of all generic processing of HTTP requests, and passing the instance to the `GraphServiceClient` which holds strongly typed models and request builders to simplify the process of creating requests and consuming responses. |
| 79 | + |
| 80 | +```py |
| 81 | + |
| 82 | +# msgraph-core |
| 83 | +from msgraph.core import GraphClient |
| 84 | + |
| 85 | +client = GraphClient(credential=credential) |
| 86 | + |
| 87 | + |
| 88 | +# msgraph-sdk |
| 89 | +from msgraph.graph_request_adapter import GraphRequestAdapter |
| 90 | +from msgraph.graph_service_client import GraphServiceClient |
| 91 | + |
| 92 | +adapter = GraphRequestAdapter(auth_provider) |
| 93 | +client = GraphServiceClient(request_adapter) |
| 94 | +``` |
| 95 | +With version 2's configuration, all your requests are authenticated without additional effort. |
| 96 | + |
| 97 | +See [this example](docs/Examples.md#creating-a-request-adapter) on how to customise the GraphRequestAdapter configuration. |
| 98 | + |
| 99 | +## Changes to graph request mechanism |
| 100 | + |
| 101 | +All requests are asynchronous by default in the `msgraph-sdk` and return a coroutine. In order to execute a request, you need to run them in an async environment using one of the available popular python async libraries `asyncio`, `anyio`, `trio`. |
| 102 | + |
| 103 | +To configure the request, you need to pass a `RequestConfiguration` object to the method call. |
| 104 | + |
| 105 | +The request method also allows you to pass your custom response handler that handles the raw Response object. By default the Response body is deserialized to the expected model type. |
| 106 | + |
| 107 | + |
| 108 | +```py |
| 109 | + |
| 110 | +# msgraph-core |
| 111 | +result = client.get('/users/userId/messages',params={'$select': 'subject','$top': '5', '$skip': '1'}) |
| 112 | +for message in result.json()['value']: |
| 113 | + print message['subject'] |
| 114 | + |
| 115 | +# msgraph-sdk |
| 116 | +query_params = MessagesRequestBuilder.MessagesRequestBuilderGetQueryParameters( |
| 117 | + select=['subject',], skip=1, top=5 |
| 118 | +) |
| 119 | +request_config = MessagesRequestBuilder.MessagesRequestBuilderGetRequestConfiguration( |
| 120 | + query_parameters=query_params, |
| 121 | +) |
| 122 | + |
| 123 | +messages = asyncio.run(client.users_by_id('userId').messages().get(request_configuration=request_config)) |
| 124 | +for msg in messages.value: |
| 125 | + print(msg.subject) |
| 126 | +``` |
| 127 | + |
| 128 | +See [the examples](docs/Examples.md) on how to pass headers in your requests. |
| 129 | + |
| 130 | +## Exception Handling |
| 131 | + |
| 132 | +Any `4xx` or `5xx` responses from the Graph API will result in an `ApiException` being thrown. |
| 133 | + |
| 134 | +```py |
| 135 | + |
| 136 | +try: |
| 137 | + users = asyncio.run(client.users().get()) |
| 138 | + |
| 139 | +except ApiException as e { |
| 140 | + return f"Exception occurred: {repr(e)}" |
| 141 | +} |
| 142 | +``` |
| 143 | +## Dependency changes |
| 144 | + |
| 145 | +- Python `3.6` is the new minimum supported Python version. |
| 146 | +- `requests` support is deprecated in favour of `httpx`. |
| 147 | +- `asyncio`/any other supported async envronment e.g `AnyIO`, `Trio`. |
0 commit comments