Skip to main content
Version: v3.x

Custom Business Logic via Python

Introduction

The Python Lambda Connector can be added to any project to incorporate custom business logic directly into your supergraph.

This can be used to enrich data returned to clients, or to write custom mutations in Python.

Prerequisites

If you've never used Hasura DDN, we recommend that you first go through the getting started. 😊

Functions or Procedures

Python functions exported from a file in the Python Lambda Connector will then be available from your Hasura DDN GraphQL API in the form of either functions or procedures.

In Hasura metadata, functions are used for read operations. They will not modify the data in the database and can only be used to retrieve data.

Conversely, procedures are used for write operations. They can modify the data in the database and can be used to create, update, or delete data.

The distinction is important in metadata because it allows the system to know what types to expect for arguments and return values.

Add the Python connector to a project

Step 1. Initialize the Python Lambda connector

Let's begin by initializing the connector on our project. In the example below, you'll see a familiar flow and use the hasura/python connector from the connector hub.

Run the following command:
ddn connector init my_python -i
  • Select hasura/python from the list of connectors.
  • Choose a port (press enter to accept the default recommended by the CLI).
  • In this example, we've called the connector my_python. You can name it something descriptive.

What did this do?

This command created the following file structure in a my_subgraph/connector/my_python directory, with the functions.py file being your connector's entrypoint:

.
├── .ddnignore
├── .env.cloud
├── .env.local
├── .gitignore
├── .hasura-connector
│ ├── ...
├── compose.yaml
├── connector.cloud.yaml
├── connector.local.yaml
├── functions.py
└── requirements.txt

Step 2. Write business logic

The template code that ships with the Python Lambda connector provides some simple examples to help explain how it works. We can replace those example functions for now.

In this simple example, we're going to transform a timestamp with timezone (eg: "2024-03-14T08:00:00Z") into a nicely formatted version for humans, eg: "8am, Thursday, March 14th, 2024."

We'll replace the all the default functions in our functions.py file with the following:

from hasura_ndc import start
from hasura_ndc.function_connector import FunctionConnector
from datetime import datetime # Don't forget to import datetime at the top of the file!

connector = FunctionConnector()

@connector.register_query
async def format_timezone_date(date_string: str) -> str:
date = datetime.fromisoformat(date_string)

day = date.day
nth = lambda d: "th" if 11 <= d <= 13 else {1: "st", 2: "nd", 3: "rd"}.get(d % 10, "th")

hours = date.hour
ampm = "pm" if hours >= 12 else "am"
hour = hours % 12 or 12

day_of_week = date.strftime("%A")
month = date.strftime("%B")
year = date.year

return f"{hour}{ampm}, {day_of_week}, {month} {day}{nth(day)}, {year}."


if __name__ == "__main__":
start(connector)

As this is a Python project, you can install any dependency!

Step 3. Track the new function

To add our function, we can use the following to generate the related metadata that will link together any functions in this functions.py file and our API.

ddn connector introspect my_python
ddn command add my_python "*"

Step 4. Create a new API build and test

Next, let's create a new build of our supergraph:

ddn supergraph build local
Start your engines!

Don't forget to start your GraphQL engine using the following command.

From the root of your project, run:
ddn run docker-start

This reads the docker-start script from the context config at .hasura/context.yaml and starts your Hasura engine, any connectors, and observability tools.

You should see your command available, along with its documentation, in the GraphiQL explorer on the console which you should be able to access using:

Run:
ddn console --local
You can then test your new command with the following query:
query MyQuery {
formatTimezoneDate(dateString: "2024-03-14")
}
Demo Business Logic query

Privacy settings in some browsers

Your browser settings or privacy tools may prevent the Console from accessing your local Hasura instance. This could be due to features designed to protect your privacy and security. Should you encounter one of these issues, we recommend disabling these settings for the console.hasura.io domain.

Chrome and Firefox are the recommended browsers for the best experience with the Hasura Console including for local development.

Running Python locally

By default, Python and your functions run in a Docker container along with your other Hasura services. The connector init command created a compose.yaml file for you, which are used by default.

However, if you prefer to run Python directly on your local machine, you can do so by following these steps:

  1. Ensure you have Python version >=3.11 installed on your machine.
  2. Install the necessary dependencies:
Change to the connector directory and install dependencies:
cd my_subgraph/connector/my_python && pip3 install -r requirements.txt
  1. From the my_python directory, run this command to load environment variables from your project's .env file, start the connector, and watch for any changes:

On Mac or Linux:

watchmedo auto-restart --patterns="*.py" --recursive -- sh -c "export \$(grep -v '^#' .env.local | xargs) && python3 functions.py serve"

On Windows:

watchmedo auto-restart --patterns="*.py" --recursive -- powershell -Command "Get-Content .env.local | ForEach-Object { if ($_ -notmatch '^#') { $var = $_.Split('='); Set-Item \"env:$($var[0])\" $var[1] } }; python3 functions.py serve"

Make sure the port specified in your connector's .env file doesn't conflict with any other services you may be running.