Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
# generally not be tracked in source control. To instruct the system to track
# .func in source control, comment the following line (prefix it with '# ').
/.func
/.s2i

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Python CloudEvents Function

Welcome to your new Python Function! A minimal Function implementation can
be found in `./function/func.py`.

For more, run `func --help` or read the [Python Functions doc](https://github.com/knative/func/blob/main/docs/function-templates/python.md)

## Usage

Knative Functions allow for the deployment of your source code directly to a
Kubernetes cluster with Knative installed.

### Function Structure

Python functions must implement a `new()` method that returns a function
instance. The function class can optionally implement:
- `handle()` - Process CloudEvent requests
- `start()` - Initialize the function with configuration
- `stop()` - Clean up resources when the function stops
- `alive()` / `ready()` - Health and readiness checks

See the default implementation in `./function/func.py`

### Running Locally

Use `func run` to test your Function locally before deployment.
For development environments where Python is installed, it's suggested to use
the `host` builder as follows:

```bash
# Run function on the host (outsdie of a container)
func run --builder=host
```

### Deploying

Use `func deploy` to deploy your Function to a Knative-enabled cluster:

```bash
# Deploy with interactive prompts (recommended for first deployment)
func deploy --registry ghcr.io/myuser
```

Functions are automatically built, containerized, and pushed to a registry
before deployment. Subsequent deployments will update the existing function.

## Roadmap

Our project roadmap can be found: https://github.com/orgs/knative/projects/49

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# $schema: https://raw.githubusercontent.com/knative/func/d04ff0a3/schema/func_yaml-schema.json
# yaml-language-server: $schema=https://raw.githubusercontent.com/knative/func/d04ff0a3/schema/func_yaml-schema.json
specVersion: 0.36.0
name: bad-word-filter
runtime: python
created: 2024-03-27T23:12:06.178272+08:00
registry: localhost:5000
namespace: default
created: 2025-09-20T18:38:53.634514281+02:00
invoke: cloudevent
build:
builder: s2i
deploy:
namespace: default
image: localhost:5000/bad-word-filter@sha256:690a4eb5aaae56dfbfabcb8a3f0943a48b97851e2b90ce40397091bb0866655c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .func import new
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import logging
from cloudevents.http import CloudEvent
from profanity_check import predict

def new():
return Function()

class Function:
async def handle(self, scope, receive, send):
""" Handle all HTTP requests to this Function. The incoming CloudEvent is in scope["event"]. """
logging.info("Request Received")

# 1. Extract the CloudEvent from the scope
request_event = scope["event"]

# 2. Extract the data payload from the event, analyze and create CloudEvent
response_event = self.inappropriate_language_filter(request_event.data)

# 3. Send the response
logging.info(f"Sending response: {response_event.data}")
await send(response_event)

def create_cloud_event(self, inputText, data):
attributes = {
"type": "new-review-comment",
"source": "book-review-broker",
"datacontenttype": "application/json",
"badwordfilter": data,
}

# Put the bad word filter result into a dictionary
data = {"reviewText": inputText, "badWordResult": data}

# Create a CloudEvent object
return CloudEvent(attributes, data)

def inappropriate_language_filter(self, text):
review_text = text.get("reviewText", "")
profanity_result = predict([review_text])
result = "good"
if profanity_result[0] == 1:
result = "bad"

return self.create_cloud_event(review_text, result)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[project]
name = "function"
description = ""
version = "0.1.0"
requires-python = ">=3.9"
readme = "README.md"
license = "MIT"
dependencies = [
"httpx",
"cloudevents",
"pytest",
"pytest-asyncio",
"alt-profanity-check==1.4.1.post1"
]
authors = [
{ name="Your Name", email="you@example.com"},
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.pytest.ini_options]
asyncio_mode = "strict"
asyncio_default_fixture_loop_scope = "function"


This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
Unit tests for the CloudEvent function implementation.
Tests both the function health endpoints and its handling of CloudEvents.

Functions are currently served as ASGI applications using hypercorn, so we
use httpx for testing. To run the tests using poetry:

poetry run python -m unittest discover
"""
import json
import asyncio
import pytest
from cloudevents.http import CloudEvent
from function import new


@pytest.mark.asyncio
async def test_func():
f = new() # Instantiate Function to Test

# A test CloudEvent
attributes = {
"id": "test-id",
"type": "com.example.test1",
"source": "https://example.com/event-producer",
}
data = {"message": "test message"}
event = CloudEvent(attributes, data)

invoked = False # Flag indicating send method was invoked

# Send
# confirms the Functions responds with a CloudEvent which echoes
# the data sent.
async def send(e):
nonlocal invoked
invoked = True # Flag send was invoked

# Ensure we got a CloudEvent
assert isinstance(e, CloudEvent), f"Expected CloudEvent, got {type(e)}"

# Ensure it echoes the data sent
assert e.data == data, f"Expected data {data}, got {e.data}"

# Invoke the Function
scope = {"event": event} # Add the CloudEvent to the scope
await f.handle(scope, {}, send)

# Assert send was called
assert invoked, "Function did not call send"
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
# generally not be tracked in source control. To instruct the system to track
# .func in source control, comment the following line (prefix it with '# ').
/.func
/.s2i

This file was deleted.

Loading
Loading