From ac4c2f5059d1f7073eb1f63856f62969379ddf2c Mon Sep 17 00:00:00 2001 From: samwelkanda Date: Thu, 25 May 2023 17:40:57 +0300 Subject: [PATCH 1/7] Refactor client instantiation logic --- msgraph/graph_service_client.py | 42 ++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/msgraph/graph_service_client.py b/msgraph/graph_service_client.py index bb382b479ab..6ea85c1f866 100644 --- a/msgraph/graph_service_client.py +++ b/msgraph/graph_service_client.py @@ -1,6 +1,46 @@ +from typing import List, Optional, TYPE_CHECKING, Union' +from azure.core.credentials import TokenCredential +from azure.core.credentials_async import AsyncTokenCredential +from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider +from httpx import AsyncClient + from .generated.base_graph_service_client import BaseGraphServiceClient from .graph_request_adapter import GraphRequestAdapter class GraphServiceClient(BaseGraphServiceClient): - def __init__(self, request_adapter: GraphRequestAdapter) -> None: + def __init__( + self, + credentials: Union[TokenCredential, AsyncTokenCredential], + scopes: Optional[List[str]], + base_url: Optional[str] = None, + client: Optional[AsyncClient] = None + ) -> None: + """Constructs a client instance to use for making requests to the + Microsoft Graph v.1.0 API. + + Args: + credentials (Union[TokenCredential, AsyncTokenCredential]): The + tokenCredential to use for authentication. + scopes (Optional[List[str]]): The scopes to use for authentication. + Defaults to ['https://graph.microsoft.com/.default']. + base_url (Optional[str], optional): The base url to use for + requests. Defaults to https://graph.microsoft.com/v1.0. + client (Optional[AsyncClient], optional): A custom httpx.AsyncClient + to use for http requests. Defaults to None. + """ + + if scopes: + auth_provider = AzureIdentityAuthenticationProvider(credentials, scopes) + else: + auth_provider = AzureIdentityAuthenticationProvider(credentials) + + if client: + request_adapter = GraphRequestAdapter(auth_provider, client) + else: + request_adapter = GraphRequestAdapter(auth_provider) + + if base_url: + request_adapter.base_url = base_url + + super().__init__(request_adapter) \ No newline at end of file From 32c06c0192454e4b0dffad84bac91cc63d602315 Mon Sep 17 00:00:00 2001 From: samwelkanda Date: Thu, 25 May 2023 17:41:17 +0300 Subject: [PATCH 2/7] Update documentation with changes --- README.md | 77 ++++++++++--------------------- samples/applications_samples.md | 13 ++---- samples/authentication_samples.md | 52 +++++++-------------- samples/drives_samples.md | 13 ++---- samples/general_samples.md | 16 ++----- samples/groups_samples.md | 13 ++---- samples/users_samples.md | 11 ++--- 7 files changed, 59 insertions(+), 136 deletions(-) diff --git a/README.md b/README.md index 7b3835dcf68..247ee52fd31 100644 --- a/README.md +++ b/README.md @@ -19,60 +19,39 @@ pip install msgraph-sdk Register your application by following the steps at [Register your app with the Microsoft Identity Platform](https://docs.microsoft.com/graph/auth-register-app-v2). -### 2.2 Create an AuthenticationProvider object +### 2.2 Initialize a GraphServiceClient object -An instance of the **GraphServiceClient** class handles building client. To create a new instance of this class, you need to provide an instance of **AuthenticationProvider**, which can authenticate requests to Microsoft Graph. +You must create **GraphServiceClient** object to make requests against the service. To create a new instance of this class, you need to provide credentials and scopes, which can authenticate requests to Microsoft Graph. > **Note**: For authentication we support both `sync` and `async` credential classes from `azure.identity`. Please see the azure identity [docs](https://learn.microsoft.com/en-us/python/api/azure-identity/azure.identity?view=azure-python) for more information. ```py -# Example using async credentials. -from azure.identity.aio import DefaultAzureCredential -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider - -credential=DefaultAzureCredential() -auth_provider = AzureIdentityAuthenticationProvider(credential) -``` - -The above example uses default scopes for [app-only access](https://learn.microsoft.com/en-us/graph/permissions-overview#delegated-permissions). If using [delegated access](https://learn.microsoft.com/en-us/graph/permissions-overview#delegated-permissions) you can provide custom scopes: - -```py -scopes = ['User.Read', 'Mail.Read'] -credential=DeviceCodeCredential() -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -``` - -### 2.3 Initialise a GraphRequestAdapter object - -The SDK uses an adapter object that handles the HTTP concerns. This HTTP adapter object is used to build the Graph client for making requests. - -To initialise one using the authentication provider created in the previous step: - -```py -from msgraph import GraphRequestAdapter - -adapter = GraphRequestAdapter(auth_provider) -``` - -We currently use [HTTPX](https://www.python-httpx.org/) as our HTTP client. You can pass your custom configured `httpx.AsyncClient` using: - -```py -import httpx -from msgraph import GraphRequestAdapter -from msgraph_core import GraphClientFactory +# Example using async credentials and application access. +from azure.identity.aio import ClientSecretCredential +from msgraph import GraphServiceClient -http_client = GraphClientFactory.create_with_default_middleware(client=httpx.AsyncClient()) -request_adapter = GraphRequestAdapter(auth_provider, http_client) +credential = ClientSecretCredential( + tenant_id='TENANT_ID', + client_id='CLIENT_ID', + client_secret='CLIENT_SECRET', +) +scopes = ['https://graph.microsoft.com/.default'] +client = GraphServiceClient(credentials, scopes=scopes) ``` -### 2.3 Get a GraphServiceClient object - -You must get a **GraphServiceClient** object to make requests against the service. +The above example uses default scopes for [app-only access](https://learn.microsoft.com/en-us/graph/permissions-overview?tabs=http#application-permissions). If using [delegated access](https://learn.microsoft.com/en-us/graph/permissions-overview#delegated-permissions) you can provide custom scopes: ```py +# Example using sync credentials and delegated access. +from azure.identity import DeviceCodeCredential from msgraph import GraphServiceClient -client = GraphServiceClient(request_adapter) +credential=DeviceCodeCredential( + client_id='CLIENT_ID', + tenant_id='TENANT_ID', +) +scopes = ['User.Read', 'Mail.Read'] +client = GraphServiceClient(credentials, scopes=scopes) ``` ## 3. Make requests against the service @@ -86,8 +65,6 @@ The following is a complete example that shows how to fetch a user from Microsof ```py import asyncio from azure.identity.aio import ClientSecretCredential -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter from msgraph import GraphServiceClient credential = ClientSecretCredential( @@ -96,9 +73,7 @@ credential = ClientSecretCredential( 'client_secret' ) scopes = ['https://graph.microsoft.com/.default'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -request_adapter = GraphRequestAdapter(auth_provider) -client = GraphServiceClient(request_adapter) +client = GraphServiceClient(credentials, scopes=scopes) async def get_user(): user = await client.users.by_user_id('userPrincipalName').get() @@ -108,20 +83,16 @@ async def get_user(): asyncio.run(get_user()) ``` -Note that to calling `me` requires a signed-in user and therefore delegated permissions. See [Authenticating Users](https://learn.microsoft.com/en-us/python/api/overview/azure/identity-readme?view=azure-python#authenticate-users)) for more: +Note that to calling `me` requires a signed-in user and therefore delegated permissions. See [Authenticating Users](https://learn.microsoft.com/en-us/python/api/overview/azure/identity-readme?view=azure-python#authenticate-users) for more: ```py import asyncio from azure.identity import InteractiveBrowserCredential -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter from msgraph import GraphServiceClient credential = InteractiveBrowserCredential() scopes=['User.Read'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -request_adapter = GraphRequestAdapter(auth_provider) -client = GraphServiceClient(request_adapter) +client = GraphServiceClient(credentials, scopes=scopes,) async def me(): me = await client.me.get() diff --git a/samples/applications_samples.md b/samples/applications_samples.md index 333a8ce6a62..d3711eeaaf0 100644 --- a/samples/applications_samples.md +++ b/samples/applications_samples.md @@ -5,22 +5,17 @@ import asyncio from azure.identity import EnvironmentCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate request +# Create a credential object. Used to authenticate requests credential=EnvironmentCredential() -auth_provider = AzureIdentityAuthenticationProvider(credential) +scopes = ['https://graph.microsoft.com/.default'] -# Initialize a request adapter. Handles the HTTP concerns. -request_adapter = GraphRequestAdapter(auth_provider) - -# Get a service client. -client = GraphServiceClient(request_adapter) +# Create an API client with the credentials and scopes +client = GraphServiceClient(credentials, scopes=scopes) ``` ## 1. LIST ALL APPLICATIONS IN THE TENANT (GET /applications) diff --git a/samples/authentication_samples.md b/samples/authentication_samples.md index a1a546026dc..ba5fd2354ea 100644 --- a/samples/authentication_samples.md +++ b/samples/authentication_samples.md @@ -7,26 +7,21 @@ import asyncio from azure.identity import DeviceCodeCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter, GraphServiceClient +from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate requests +# Create a credential object. Used to authenticate requests credential = DeviceCodeCredential( client_id='CLIENT_ID', tenant_id='TENANT_ID', ) scopes = ["User.Read"] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -# Initialize a request adapter with the auth provider. -request_adapter = GraphRequestAdapter(auth_provider) - -# Create an API client with the request adapter. -client = GraphServiceClient(request_adapter) +# Create an API client with the credentials and scopes. +client = GraphServiceClient(credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): @@ -46,22 +41,17 @@ asyncio.run(get_user()) import asyncio from azure.identity import InteractiveBrowserCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter, GraphServiceClient +from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate requests +# Create a credential object. Used to authenticate requests credential = InteractiveBrowserCredential() scopes = ["User.Read"] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) - -# Initialize a request adapter with the auth provider. -request_adapter = GraphRequestAdapter(auth_provider) -# Create an API client with the request adapter. -client = GraphServiceClient(request_adapter) +# Create an API client with the credentials and scopes. +client = GraphServiceClient(credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): @@ -83,26 +73,21 @@ import asyncio from azure.identity import ClientSecretCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter, GraphServiceClient +from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate request +# Create a credential object. Used to authenticate requests credential = ClientSecretCredential( tenant_id='TENANT_ID', client_id='CLIENT_ID', client_secret='CLIENT_SECRET' ) scopes = ['https://graph.microsoft.com/.default'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -# Initialize a request adapter with the auth provider. -request_adapter = GraphRequestAdapter(auth_provider) - -# Create an API client with the request adapter. -client = GraphServiceClient(request_adapter) +# Create an API client with the credentials and scopes. +client = GraphServiceClient(credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): @@ -122,22 +107,17 @@ import asyncio from azure.identity.aio import EnvironmentCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter, GraphServiceClient +from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate request +# Create a credential object. Used to authenticate requests credential = EnvironmentCredential() scopes = ['https://graph.microsoft.com/.default'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) - -# Initialize a request adapter with the auth provider. -request_adapter = GraphRequestAdapter(auth_provider) -# Create an API client with the request adapter. -client = GraphServiceClient(request_adapter) +# Create an API client with the credentials and scopes. +client = GraphServiceClient(credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): diff --git a/samples/drives_samples.md b/samples/drives_samples.md index 65ef191c465..c3d82af16f4 100644 --- a/samples/drives_samples.md +++ b/samples/drives_samples.md @@ -5,26 +5,21 @@ import asyncio from azure.identity import ClientSecretCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter, GraphServiceClient +from msgraph import GraphServiceClient # (Optional) Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate request +# Create a credential object. Used to authenticate requests credential = ClientSecretCredential( tenant_id='TENANT_ID', client_id='CLIENT_ID', client_secret='CLIENT_SECRET' ) scopes = ['https://graph.microsoft.com/.default'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -# Initialize a request adapter with the auth provider. -request_adapter = GraphRequestAdapter(auth_provider) - -# Create an API client with the request adapter. -client = GraphServiceClient(request_adapter) +# Create an API client with the credentials and scopes. +client = GraphServiceClient() ``` ## 1. LIST ALL DRIVES (GET /drives) diff --git a/samples/general_samples.md b/samples/general_samples.md index 2745bc226a5..bc3148e4b28 100644 --- a/samples/general_samples.md +++ b/samples/general_samples.md @@ -6,23 +6,19 @@ This creates a default Graph client that uses `https://graph.microsoft.com` as t ```py from azure.identity import AuthorizationCodeCredential from kiota_abstactions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -AuthorizationCodeCredential( +credentials = AuthorizationCodeCredential( tenant_id: str, client_id: str, authorization_code: str, redirect_uri: str ) scopes = ['User.Read', 'Mail.ReadWrite'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -request_adapter = GraphRequestAdapter(auth_provider) -client = GraphServiceClient(request_adapter) +client = GraphServiceClient(credentials, scopes=scopes) ``` ## 2. Creating a Graph client using a custom `httpx.AsyncClient` instance @@ -32,7 +28,7 @@ from msgraph import GraphRequestAdapter from msgraph_core import GraphClientFactory http_client = GraphClientFactory.create_with_default_middleware(client=httpx.AsyncClient()) -request_adapter = GraphRequestAdapter(auth_provider, http_client) +client = GraphServiceClient(credentials, scopes=scopes, client=http_client) ``` ## 3. Get an item from the Microsoft Graph API @@ -144,8 +140,6 @@ Ensure you have the [right permissions](https://docs.microsoft.com/en-us/graph/a ```py from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter from msgraph import GraphServiceClient from msgraph.generated.me.send_mail.send_mail_post_request_body import SendMailPostRequestBody @@ -165,9 +159,7 @@ credential = ClientSecretCredential( 'client_secret' ) scopes = ['Mail.Send'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -request_adapter = GraphRequestAdapter(auth_provider) -client = GraphServiceClient(request_adapter) +client = GraphServiceClient(credential, scopes=scopes) async def send_mail(): try: diff --git a/samples/groups_samples.md b/samples/groups_samples.md index 19a5410d794..93718e559c9 100644 --- a/samples/groups_samples.md +++ b/samples/groups_samples.md @@ -5,26 +5,21 @@ import asyncio from azure.identity import ClientSecretCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter, GraphServiceClient +from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate request +# Create a credential object. Used to authenticate requests credential = ClientSecretCredential( tenant_id='TENANT_ID', client_id='CLIENT_ID', client_secret='CLIENT_SECRET' ) scopes = ['https://graph.microsoft.com/.default'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -# Initialize a request adapter with the auth provider. -request_adapter = GraphRequestAdapter(auth_provider) - -# Create an API client with the request adapter. -client = GraphServiceClient(request_adapter) +# Create an API client with the credentials and scopes. +client = GraphServiceClient(credential, scopes=scopes) ``` ## 1. LIST ALL GROUPS IN THE TENANT (GET /groups) diff --git a/samples/users_samples.md b/samples/users_samples.md index ad9f5084619..ae0c9fd2a8c 100644 --- a/samples/users_samples.md +++ b/samples/users_samples.md @@ -5,25 +5,20 @@ import asyncio from azure.identity import ClientSecretCredential from kiota_abstractions.api_error import APIError -from kiota_authentication_azure.azure_identity_authentication_provider import AzureIdentityAuthenticationProvider -from msgraph import GraphRequestAdapter, GraphServiceClient +from msgraph import GraphServiceClient # Set the event loop policy for Windows asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -# Create authentication provider object. Used to authenticate request +# Create a credential object. Used to authenticate requests credential = ClientSecretCredential( tenant_id='TENANT_ID', client_id='CLIENT_ID', client_secret='CLIENT_SECRET' ) scopes = ['https://graph.microsoft.com/.default'] -auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=scopes) -# Initialize a request adapter with the auth provider. -request_adapter = GraphRequestAdapter(auth_provider) - -# Create an API client with the request adapter. +# Create an API client with the credentials and scopes. client = GraphServiceClient(request_adapter) ``` From 048110e3a67c8de1eccd0cb1a3b38d83a85e6eac Mon Sep 17 00:00:00 2001 From: samwelkanda Date: Thu, 25 May 2023 17:44:29 +0300 Subject: [PATCH 3/7] Add CHANGELOG entry --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cdc84692fc..6685e911e02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.0a13] - 2023-05-25 + +### Added + +### Changed + +- Simplified the creation of a graph client. [#180](https://github.com/microsoftgraph/msgraph-sdk-python/issues/180) + ## [1.0.0a12] - 2023-04-19 ### Added From e3f8f0833d64512b160f0933e3ce0eb427d4413b Mon Sep 17 00:00:00 2001 From: samwelkanda Date: Thu, 25 May 2023 17:44:38 +0300 Subject: [PATCH 4/7] bump version 1.0.0a12 -> 1.0.0a13 --- msgraph/_version.py | 2 +- pyproject.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/msgraph/_version.py b/msgraph/_version.py index ac91a4cd3a1..b9429e3aef5 100644 --- a/msgraph/_version.py +++ b/msgraph/_version.py @@ -1 +1 @@ -VERSION: str = '1.0.0a12' \ No newline at end of file +VERSION: str = '1.0.0a13' \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 2c7b90a93a6..fd312de5d39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "msgraph-sdk" -version = "1.0.0a12" +version = "1.0.0a13" authors = [{name = "Microsoft", email = "graphtooling+python@microsoft.com"}] description = "The Microsoft Graph Python SDK" dependencies = [ @@ -59,7 +59,7 @@ pythonpath = [ ] [tool.bumpver] -current_version = "1.0.0a12" +current_version = "1.0.0a13" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = true From 6e1217fb7305756effedd2b832585b5eb176e23f Mon Sep 17 00:00:00 2001 From: samwelkanda Date: Thu, 25 May 2023 17:49:13 +0300 Subject: [PATCH 5/7] Correct ommissions --- samples/drives_samples.md | 3 ++- samples/users_samples.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/drives_samples.md b/samples/drives_samples.md index c3d82af16f4..b003155ad60 100644 --- a/samples/drives_samples.md +++ b/samples/drives_samples.md @@ -19,7 +19,8 @@ credential = ClientSecretCredential( scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes. -client = GraphServiceClient() +client = GraphServiceClient(credentials, scopes=scopes) +``` ``` ## 1. LIST ALL DRIVES (GET /drives) diff --git a/samples/users_samples.md b/samples/users_samples.md index ae0c9fd2a8c..10c82175e07 100644 --- a/samples/users_samples.md +++ b/samples/users_samples.md @@ -19,7 +19,7 @@ credential = ClientSecretCredential( scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes. -client = GraphServiceClient(request_adapter) +client = GraphServiceClient(credential, scopes=scopes) ``` ## 1. GET ALL USERS IN A TENANT (GET /users) From cf453688162a33fac5c00b49cc6eaf5739589b14 Mon Sep 17 00:00:00 2001 From: samwelkanda Date: Thu, 25 May 2023 18:09:18 +0300 Subject: [PATCH 6/7] Refactor to allow passing request adapter object --- README.md | 8 +++---- msgraph/graph_service_client.py | 35 +++++++++++++------------------ samples/applications_samples.md | 4 ++-- samples/authentication_samples.md | 8 +++---- samples/drives_samples.md | 3 +-- samples/general_samples.md | 7 ++++--- samples/groups_samples.md | 2 +- samples/users_samples.md | 2 +- 8 files changed, 32 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 247ee52fd31..0d35d598f57 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ credential = ClientSecretCredential( client_secret='CLIENT_SECRET', ) scopes = ['https://graph.microsoft.com/.default'] -client = GraphServiceClient(credentials, scopes=scopes) +client = GraphServiceClient(credentials=credentials, scopes=scopes) ``` The above example uses default scopes for [app-only access](https://learn.microsoft.com/en-us/graph/permissions-overview?tabs=http#application-permissions). If using [delegated access](https://learn.microsoft.com/en-us/graph/permissions-overview#delegated-permissions) you can provide custom scopes: @@ -51,7 +51,7 @@ credential=DeviceCodeCredential( tenant_id='TENANT_ID', ) scopes = ['User.Read', 'Mail.Read'] -client = GraphServiceClient(credentials, scopes=scopes) +client = GraphServiceClient(credentials=credentials, scopes=scopes) ``` ## 3. Make requests against the service @@ -73,7 +73,7 @@ credential = ClientSecretCredential( 'client_secret' ) scopes = ['https://graph.microsoft.com/.default'] -client = GraphServiceClient(credentials, scopes=scopes) +client = GraphServiceClient(credentials=credentials, scopes=scopes) async def get_user(): user = await client.users.by_user_id('userPrincipalName').get() @@ -92,7 +92,7 @@ from msgraph import GraphServiceClient credential = InteractiveBrowserCredential() scopes=['User.Read'] -client = GraphServiceClient(credentials, scopes=scopes,) +client = GraphServiceClient(credentials=credentials, scopes=scopes,) async def me(): me = await client.me.get() diff --git a/msgraph/graph_service_client.py b/msgraph/graph_service_client.py index 6ea85c1f866..d3872741244 100644 --- a/msgraph/graph_service_client.py +++ b/msgraph/graph_service_client.py @@ -10,10 +10,10 @@ class GraphServiceClient(BaseGraphServiceClient): def __init__( self, - credentials: Union[TokenCredential, AsyncTokenCredential], - scopes: Optional[List[str]], - base_url: Optional[str] = None, - client: Optional[AsyncClient] = None + credentials: Optional[Union[TokenCredential, AsyncTokenCredential]] = None, + scopes: Optional[List[str]] = None, + request_adapter: Optional[GraphRequestAdapter] = None + ) -> None: """Constructs a client instance to use for making requests to the Microsoft Graph v.1.0 API. @@ -23,24 +23,19 @@ def __init__( tokenCredential to use for authentication. scopes (Optional[List[str]]): The scopes to use for authentication. Defaults to ['https://graph.microsoft.com/.default']. - base_url (Optional[str], optional): The base url to use for - requests. Defaults to https://graph.microsoft.com/v1.0. - client (Optional[AsyncClient], optional): A custom httpx.AsyncClient - to use for http requests. Defaults to None. + request_adapter (Optional[GraphRequestAdapter], optional): The + request adapter to use for requests. Defaults to None. """ - if scopes: - auth_provider = AzureIdentityAuthenticationProvider(credentials, scopes) - else: - auth_provider = AzureIdentityAuthenticationProvider(credentials) - - if client: - request_adapter = GraphRequestAdapter(auth_provider, client) - else: + if not request_adapter: + if not credentials: + raise ValueError("Missing request adapter or valid credentials") + + if scopes: + auth_provider = AzureIdentityAuthenticationProvider(credentials, scopes) + else: + auth_provider = AzureIdentityAuthenticationProvider(credentials) + request_adapter = GraphRequestAdapter(auth_provider) - if base_url: - request_adapter.base_url = base_url - - super().__init__(request_adapter) \ No newline at end of file diff --git a/samples/applications_samples.md b/samples/applications_samples.md index d3711eeaaf0..81344d2f8fa 100644 --- a/samples/applications_samples.md +++ b/samples/applications_samples.md @@ -11,11 +11,11 @@ from msgraph import GraphServiceClient asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # Create a credential object. Used to authenticate requests -credential=EnvironmentCredential() +credentials = EnvironmentCredential() scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes -client = GraphServiceClient(credentials, scopes=scopes) +client = GraphServiceClient(credentials=credentials, scopes=scopes) ``` ## 1. LIST ALL APPLICATIONS IN THE TENANT (GET /applications) diff --git a/samples/authentication_samples.md b/samples/authentication_samples.md index ba5fd2354ea..20856ea7733 100644 --- a/samples/authentication_samples.md +++ b/samples/authentication_samples.md @@ -21,7 +21,7 @@ credential = DeviceCodeCredential( scopes = ["User.Read"] # Create an API client with the credentials and scopes. -client = GraphServiceClient(credential, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): @@ -51,7 +51,7 @@ credential = InteractiveBrowserCredential() scopes = ["User.Read"] # Create an API client with the credentials and scopes. -client = GraphServiceClient(credential, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): @@ -87,7 +87,7 @@ credential = ClientSecretCredential( scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes. -client = GraphServiceClient(credential, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): @@ -117,7 +117,7 @@ credential = EnvironmentCredential() scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes. -client = GraphServiceClient(credential, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) # GET A USER USING THE USER ID (GET /users/{id}) async def get_user(): diff --git a/samples/drives_samples.md b/samples/drives_samples.md index b003155ad60..8256b1922cb 100644 --- a/samples/drives_samples.md +++ b/samples/drives_samples.md @@ -19,8 +19,7 @@ credential = ClientSecretCredential( scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes. -client = GraphServiceClient(credentials, scopes=scopes) -``` +client = GraphServiceClient(credentials=credential, scopes=scopes) ``` ## 1. LIST ALL DRIVES (GET /drives) diff --git a/samples/general_samples.md b/samples/general_samples.md index bc3148e4b28..b4dd9784e2f 100644 --- a/samples/general_samples.md +++ b/samples/general_samples.md @@ -18,7 +18,7 @@ credentials = AuthorizationCodeCredential( redirect_uri: str ) scopes = ['User.Read', 'Mail.ReadWrite'] -client = GraphServiceClient(credentials, scopes=scopes) +client = GraphServiceClient(credentials=credentials, scopes=scopes) ``` ## 2. Creating a Graph client using a custom `httpx.AsyncClient` instance @@ -28,7 +28,8 @@ from msgraph import GraphRequestAdapter from msgraph_core import GraphClientFactory http_client = GraphClientFactory.create_with_default_middleware(client=httpx.AsyncClient()) -client = GraphServiceClient(credentials, scopes=scopes, client=http_client) +request_adapter = GraphRequestAdapter(auth_provider, http_client) +client = GraphServiceClient(request_adapter=request_adapter) ``` ## 3. Get an item from the Microsoft Graph API @@ -159,7 +160,7 @@ credential = ClientSecretCredential( 'client_secret' ) scopes = ['Mail.Send'] -client = GraphServiceClient(credential, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) async def send_mail(): try: diff --git a/samples/groups_samples.md b/samples/groups_samples.md index 93718e559c9..7a3ea165831 100644 --- a/samples/groups_samples.md +++ b/samples/groups_samples.md @@ -19,7 +19,7 @@ credential = ClientSecretCredential( scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes. -client = GraphServiceClient(credential, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) ``` ## 1. LIST ALL GROUPS IN THE TENANT (GET /groups) diff --git a/samples/users_samples.md b/samples/users_samples.md index 10c82175e07..266840913de 100644 --- a/samples/users_samples.md +++ b/samples/users_samples.md @@ -19,7 +19,7 @@ credential = ClientSecretCredential( scopes = ['https://graph.microsoft.com/.default'] # Create an API client with the credentials and scopes. -client = GraphServiceClient(credential, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) ``` ## 1. GET ALL USERS IN A TENANT (GET /users) From 15318d5bd30ab0a9ea6b62533f3a922d68d851f3 Mon Sep 17 00:00:00 2001 From: samwelkanda Date: Thu, 25 May 2023 18:14:00 +0300 Subject: [PATCH 7/7] Fix typos --- README.md | 8 ++++---- msgraph/graph_service_client.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0d35d598f57..984aa107b86 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ credential = ClientSecretCredential( client_secret='CLIENT_SECRET', ) scopes = ['https://graph.microsoft.com/.default'] -client = GraphServiceClient(credentials=credentials, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) ``` The above example uses default scopes for [app-only access](https://learn.microsoft.com/en-us/graph/permissions-overview?tabs=http#application-permissions). If using [delegated access](https://learn.microsoft.com/en-us/graph/permissions-overview#delegated-permissions) you can provide custom scopes: @@ -51,7 +51,7 @@ credential=DeviceCodeCredential( tenant_id='TENANT_ID', ) scopes = ['User.Read', 'Mail.Read'] -client = GraphServiceClient(credentials=credentials, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) ``` ## 3. Make requests against the service @@ -73,7 +73,7 @@ credential = ClientSecretCredential( 'client_secret' ) scopes = ['https://graph.microsoft.com/.default'] -client = GraphServiceClient(credentials=credentials, scopes=scopes) +client = GraphServiceClient(credentials=credential, scopes=scopes) async def get_user(): user = await client.users.by_user_id('userPrincipalName').get() @@ -92,7 +92,7 @@ from msgraph import GraphServiceClient credential = InteractiveBrowserCredential() scopes=['User.Read'] -client = GraphServiceClient(credentials=credentials, scopes=scopes,) +client = GraphServiceClient(credentials=credential, scopes=scopes,) async def me(): me = await client.me.get() diff --git a/msgraph/graph_service_client.py b/msgraph/graph_service_client.py index d3872741244..9decd470433 100644 --- a/msgraph/graph_service_client.py +++ b/msgraph/graph_service_client.py @@ -23,8 +23,8 @@ def __init__( tokenCredential to use for authentication. scopes (Optional[List[str]]): The scopes to use for authentication. Defaults to ['https://graph.microsoft.com/.default']. - request_adapter (Optional[GraphRequestAdapter], optional): The - request adapter to use for requests. Defaults to None. + request_adapter (Optional[GraphRequestAdapter], optional): The request + adapter to use for requests. Defaults to None. """ if not request_adapter: