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.

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.