step
python_function
Execute custom Python code to transform events with full programming flexibility.
Overview
This step runs user-provided Python code in a secure Pyodide sandbox, allowing you to
implement any custom transformation logic that built-in steps don't cover. Your code
is loaded once at workflow startup, and the specified handler function is called for
each event. The function receives the event as a dictionary and must return the modified
event. You can use Python's standard library to manipulate data, perform calculations,
call external functions, or implement complex business logic. The sandbox ensures isolation
and security while giving you the full power of Python for data transformation.
Package Installation:
Use the 'requirements' field to install third-party packages via micropip.
You can specify exact versions or version ranges using standard pip syntax:
- 'package_name' - Latest version
- 'package_name==1.2.3' - Exact version
- 'package_name>=1.0.0' - Minimum version
- 'package_name>=1.0.0,<2.0.0' - Version range
- 'package_name~=1.2.0' - Compatible version
Check available packages at: https://pyodide.org/en/stable/usage/packages-in-pyodide.html
Note: Not all PyPI packages work in Pyodide (WebAssembly environment).
Pure Python packages generally work well, but packages with C extensions may not.
implement any custom transformation logic that built-in steps don't cover. Your code
is loaded once at workflow startup, and the specified handler function is called for
each event. The function receives the event as a dictionary and must return the modified
event. You can use Python's standard library to manipulate data, perform calculations,
call external functions, or implement complex business logic. The sandbox ensures isolation
and security while giving you the full power of Python for data transformation.
Package Installation:
Use the 'requirements' field to install third-party packages via micropip.
You can specify exact versions or version ranges using standard pip syntax:
- 'package_name' - Latest version
- 'package_name==1.2.3' - Exact version
- 'package_name>=1.0.0' - Minimum version
- 'package_name>=1.0.0,<2.0.0' - Version range
- 'package_name~=1.2.0' - Compatible version
Check available packages at: https://pyodide.org/en/stable/usage/packages-in-pyodide.html
Note: Not all PyPI packages work in Pyodide (WebAssembly environment).
Pure Python packages generally work well, but packages with C extensions may not.
Examples
Combine and format fields
Create derived fields from existing data
type: python_function
code: |
def process(event):
event['full_name'] = f"{event['first_name']} {event['last_name']}"
event['display_name'] = event['full_name'].title()
return event
handler: process
Calculate totals and taxes
Perform financial calculations on order data
type: python_function
code: |
def process(event):
subtotal = event['quantity'] * event['price']
tax_rate = 0.08
tax = subtotal * tax_rate
event['subtotal'] = round(subtotal, 2)
event['tax'] = round(tax, 2)
event['total'] = round(subtotal + tax, 2)
return event
handler: process
Clean and normalize data
Remove sensitive fields and normalize formats
type: python_function
code: |
def process(event):
# Remove sensitive fields
for field in ['password', 'ssn', 'credit_card']:
event.pop(field, None)
# Normalize email and phone
if 'email' in event:
event['email'] = event['email'].lower().strip()
if 'phone' in event:
event['phone'] = ''.join(filter(str.isdigit, event['phone']))
return event
handler: process
Parse and transform dates
Convert date strings to different formats
type: python_function
code: |
from datetime import datetime
def process(event):
if 'date_string' in event:
dt = datetime.strptime(event['date_string'], '%Y-%m-%d')
event['formatted_date'] = dt.strftime('%B %d, %Y')
event['day_of_week'] = dt.strftime('%A')
event['timestamp'] = int(dt.timestamp())
return event
handler: process
Conditional logic and categorization
Apply business rules to categorize data
type: python_function
code: |
def process(event):
score = event.get('score', 0)
if score >= 90:
event['grade'] = 'A'
event['category'] = 'excellent'
elif score >= 80:
event['grade'] = 'B'
event['category'] = 'good'
elif score >= 70:
event['grade'] = 'C'
event['category'] = 'average'
else:
event['grade'] = 'F'
event['category'] = 'needs_improvement'
event['passed'] = score >= 70
return event
handler: process
Array and string manipulation
Process arrays and strings with Python methods
type: python_function
code: |
def process(event):
# Split comma-separated tags into list
if 'tags' in event and isinstance(event['tags'], str):
event['tags'] = [tag.strip() for tag in event['tags'].split(',')]
# Create acronym from title
if 'title' in event:
words = event['title'].split()
event['acronym'] = ''.join(w[0].upper() for w in words if w)
# Count unique values
if 'items' in event:
event['unique_items'] = len(set(event['items']))
return event
handler: process
Convert HTML to plain text with html2text
Extract clean text from HTML content using the html2text package
type: python_function
requirements:
- html2text
code: |
import html2text
def process(event):
if 'html_content' in event:
h = html2text.HTML2Text()
h.ignore_links = False
h.ignore_images = True
event['text_content'] = h.handle(event['html_content'])
return event
handler: process
Parse HTML with BeautifulSoup
Extract data from HTML using BeautifulSoup with version requirement
type: python_function
requirements:
- beautifulsoup4>=4.9.0
code: |
from bs4 import BeautifulSoup
def process(event):
if 'html' in event:
soup = BeautifulSoup(event['html'], 'html.parser')
event['title'] = soup.find('title').get_text() if soup.find('title') else None
event['links'] = [a.get('href') for a in soup.find_all('a', href=True)]
event['paragraphs'] = [p.get_text() for p in soup.find_all('p')]
return event
handler: process
Multiple packages with version constraints
Use multiple third-party packages with specific version requirements
type: python_function
requirements:
- regex>=2023.0.0
- python-dateutil~=2.8.0
code: |
import regex
from dateutil import parser as date_parser
def process(event):
# Extract emails using regex
if 'text' in event:
email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
event['emails'] = regex.findall(email_pattern, event['text'])
# Parse flexible date formats
if 'date_string' in event:
try:
dt = date_parser.parse(event['date_string'])
event['parsed_date'] = dt.isoformat()
except:
event['parsed_date'] = None
return event
handler: process
Configuration
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Python source code that defines your handler. The code runs once inside the sandboxed module namespace. |
handler | string | Yes | Name of the function declared in 'code'. It must accept a dict event and return the transformed event (or None). |
requirements | string | No | List of Python packages to install via micropip. Supports version specifiers (==, >=, <=, !=, ~=, <, >). Examples: ['requests', 'beautifulsoup4>=4.9.0', 'numpy~=2.2.0'] |
Base Configuration
These configuration options are available on all steps:
| Parameter | Type | Default | Description |
|---|---|---|---|
name | | null | Optional name for this step (for documentation and debugging) |
description | | null | Optional description of what this step does |
retries | integer | 0 | Number of retry attempts (0-10) |
backoff_seconds | number | 0 | Backoff (seconds) applied between retry attempts |
retry_propagate | boolean | false | If True, raise last exception after exhausting retries; otherwise swallow. |