Using GraphQL with Python

Learn how to run GraphQL queries and mutations using Python.

Overview

Using Python with GraphQL allows you to efficiently retrieve and manipulate data. You can develop scripts that take full advantage of GraphQL's ability to fetch complex, interrelated data with a single request.

In this tutorial, you will learn how to create and run GraphQL queries and mutations using Python scripts. To provide examples, we will create the following scripts:

  • A script with a GraphQL query that retrieves Application Fact Sheets
  • A script with a GraphQL mutation that adds a comment to a specific Fact Sheet

Prerequisites

Before you start, do the following:

  • Install the latest LTS version of Python.

  • Install Poetry, a tool for dependency management and packaging in Python.

    📘

    Note

    You can create Python virtual environments using various methods. We recommend using Poetry. It simplifies dependency management, provides a consistent environment for development, and enhances the overall project organization.

  • Install the necessary dependencies. In this tutorial, we use the requests Python library. You can install it by executing the following command:

    poetry add requests
    
  • Learn how to authenticate to SAP LeanIX APIs. Fore more information, see Authentication to SAP LeanIX Services.

This tutorial assumes you have basic knowledge of:

  • Python and Python virtual environments
  • GraphQL

Step 1: Create a Python Project

To get started, create a new Python project.

poetry new leanix-graphql-tutorial

Poetry generates a basic Python project within the leanix-graphql-tutorial directory.

Change your working directory.

cd leanix-graphql-tutorial

Step 2: Create and Run a Python GraphQL Query Script

GraphQL queries allow you to retrieve data, similar to GET methods in REST APIs.

Create and run a Python script to retrieve all Application Fact Sheets for a Workspace using a GraphQL query. In the example, we only retrieve the id and name of Fact Sheets.

Follow these steps:

  1. In your integrated development environment (IDE), create a Python file named query.py and paste the following code into it:

    import os
    import requests
    import json
    
    LEANIX_API_TOKEN = os.getenv('LEANIX_API_TOKEN')
    LEANIX_SUBDOMAIN = os.getenv('LEANIX_SUBDOMAIN')
    LEANIX_GRAPHQL_URL = f'https://{LEANIX_SUBDOMAIN}.leanix.net/services/pathfinder/v1/graphql'
    LEANIX_OAUTH2_URL = f'https://{LEANIX_SUBDOMAIN}.leanix.net/services/mtm/v1/oauth2/token'
    
    
    def _obtain_access_token() -> str:
        """Obtains a LeanIX Access token using the Technical User generated
        API secret.
    
        Returns:
            str: The LeanIX Access Token
        """
        if not LEANIX_API_TOKEN:
            raise Exception('A valid token is required')
        response = requests.post(
            LEANIX_OAUTH2_URL,
            auth=("apitoken", LEANIX_API_TOKEN),
            data={"grant_type": "client_credentials"},
        )
        response.raise_for_status()
        return response.json().get('access_token')
    
    
    def main():
        """Executes a query against the LeanIX GraphQL API and prints
        the output.
        """
        access_token = _obtain_access_token()
        graphql_query = """{
            allFactSheets(factSheetType: Application) {
                totalCount
                edges {
                    node {
                        id
                        name
                    }
                }
            }
        }"""
    
        data = {'query': graphql_query}
        auth_header = f'Bearer {access_token}'
    
        response = requests.post(
            url=LEANIX_GRAPHQL_URL,
            headers={'Authorization': auth_header},
            data=json.dumps(data)
        )
        response.raise_for_status()
        print(response.json())
    
    
    if __name__ == '__main__':
        main()
    

    📘

    Note

    To minimize the possibility of unintentionally exposing sensitive data, we use environment variables for the LEANIX_API_TOKEN and LEANIX_SUBDOMAIN parameters instead of embedding them directly within the script. This approach allows you to isolate sensitive information and safeguard it from unauthorized access.

  2. Launch your terminal application and navigate to the project directory. Once there, execute the following command:

    LEANIX_SUBDOMAIN="{{YOUR_LEANIX_SUBDOMAIN}}" LEANIX_API_TOKEN="{{YOUR_LEANIX_API_TOKEN}}" poetry run python main.py
    

You get a response in your console that contains a list of Application Fact Sheets for your Workspace.

Example response:

{
  "data": {
    "allFactSheets": {
      "totalCount": 1,
      "edges": [
        {
          "node": {
            "id": "13f60713-4b8e-40b3-b680-64262d0e0e64",
            "name": "AC Management"
          }
        }
      ]
    }
  }
}

Step 3: Create and Run a Python GraphQL Mutation Script

GraphQL mutations allow you to update data, similar to POST, PUT, PATCH, and DELETE methods in REST APIs.

Create and run a Python script to add a comment to a Fact Sheet using a GraphQL mutation. In the example, we add a comment to the Fact Sheet that we retrieved in the previous step.

Follow these steps:

  1. Within the directory that contains the query.py file, create a Python file named mutate.py and paste the following code into it:

    import os
    import requests
    import json
    
    LEANIX_API_TOKEN = os.getenv('LEANIX_API_TOKEN')
    LEANIX_SUBDOMAIN = os.getenv('LEANIX_SUBDOMAIN')
    LEANIX_GRAPHQL_URL = f'https://{LEANIX_SUBDOMAIN}.leanix.net/services/pathfinder/v1/graphql'
    LEANIX_OAUTH2_URL = f'https://{LEANIX_SUBDOMAIN}.leanix.net/services/mtm/v1/oauth2/token'
    
    
    def _obtain_access_token() -> str:
        """Obtains a LeanIX Access token using the Technical User generated
        API secret.
    
        Returns:
            str: The LeanIX Access Token
        """
        if not LEANIX_API_TOKEN:
            raise Exception('A valid token is required')
        response = requests.post(
            LEANIX_OAUTH2_URL,
            auth=("apitoken", LEANIX_API_TOKEN),
            data={"grant_type": "client_credentials"},
        )
        response.raise_for_status()
        return response.json().get('access_token')
    
    
    def main():
        """Executes a mutation against the LeanIX GraphQL API and prints
        the output.
        """
        access_token = _obtain_access_token()
        factsheet_id = '13f60713-4b8e-40b3-b680-64262d0e0e64'
        factsheet_comment = 'What successor is planned for this?'
        graphql_mutation = """
            mutation {
                createComment(factSheetId: "%s", message: "%s", status: ACTIVE) {
                    id
                    message
                }
            }
        """ % (factsheet_id, factsheet_comment)
    
        data = {'query': graphql_mutation}
        auth_header = f'Bearer {access_token}'
    
        response = requests.post(
            url=LEANIX_GRAPHQL_URL,
            headers={'Authorization': auth_header},
            data=json.dumps(data)
        )
        response.raise_for_status()
        print(response.json())
    
    
    if __name__ == '__main__':
        main()
    
  2. Launch your terminal application and navigate to the project directory. Once there, execute the following command:

    LEANIX_SUBDOMAIN="{{YOUR_LEANIX_SUBDOMAIN}}" LEANIX_API_TOKEN="{{YOUR_LEANIX_API_TOKEN}}" poetry run python mutate.py
    

You get a response in your console that contains the comment id and message.

Example response:

{
  "data": {
    "createComment": {
      "id": "4f45247c-fdc5-4650-a4c7-6af39e3d7d64",
      "message": "What successor is planned for this?"
    }
  }
}

Step 4: Validate the Mutation Script

To validate the mutation script, you can retrieve the comment that you added using the factSheet GraphQL query. To do this, we'll modify our existing query.py script.

Follow these steps:

  1. In the query.py file, replace the main function with the following code:

    def main():
        """Executes a query against the LeanIX GraphQL API and prints
        the output.
        """
        factsheet_id = '13f60713-4b8e-40b3-b680-64262d0e0e64'
        access_token = _obtain_access_token()
        graphql_query = """
        {
            factSheet(id: "%s") {
                comments {
                    edges {
                        node {
                            id
                            message
                        }
                    }
                }
            }
        }
        """ % (factsheet_id)
    
        data = {'query': graphql_query}
        auth_header = f'Bearer {access_token}'
    
        response = requests.post(
            url=LEANIX_GRAPHQL_URL,
            headers={'Authorization': auth_header},
            data=json.dumps(data)
        )
        response.raise_for_status()
        print(response.json())
    
  2. Execute the query.py script.

    LEANIX_SUBDOMAIN="{{YOUR_LEANIX_SUBDOMAIN}}" LEANIX_API_TOKEN="{{YOUR_LEANIX_API_TOKEN}}" poetry run python query.py
    

You get a response in your console that contains the comment id and message, which confirms that the mutation script works as expected.

Example response:

{
  "data": {
    "factSheet": {
      "comments": {
        "edges": [
          {
            "node": {
              "id": "4f45247c-fdc5-4650-a4c7-6af39e3d7d64",
              "message": "What successor is planned for this?"
            }
          }
        ]
      }
    }
  }
}

To view comments in the application user interface, navigate to the Comments tab on a Fact Sheet.

Summary

In this tutorial, you learned how to create and run GraphQL queries and mutations using Python scripts.