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.
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.
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
Don't forget to start your GraphQL engine using the following command.
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:
ddn console --local
query MyQuery {
formatTimezoneDate(dateString: "2024-03-14")
}
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.
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:
- Ensure you have Python version
>=3.11
installed on your machine. - Install the necessary dependencies:
cd my_subgraph/connector/my_python && pip3 install -r requirements.txt
- 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.