feat: add new examples from pocketflow-academy
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# SQLite Database with PocketFlow
|
||||
|
||||
This example demonstrates how to properly integrate SQLite database operations with PocketFlow, focusing on:
|
||||
|
||||
1. Clean code organization with separation of concerns:
|
||||
- Tools layer for database operations (`tools/database.py`)
|
||||
- Node implementation for PocketFlow integration (`nodes.py`)
|
||||
- Flow configuration (`flow.py`)
|
||||
- Safe SQL query execution with parameter binding
|
||||
|
||||
2. Best practices for database operations:
|
||||
- Connection management with proper closing
|
||||
- SQL injection prevention using parameterized queries
|
||||
- Error handling and resource cleanup
|
||||
- Simple schema management
|
||||
|
||||
3. Example task management system:
|
||||
- Database initialization
|
||||
- Task creation
|
||||
- Task listing
|
||||
- Status tracking
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
pocketflow-tool-database/
|
||||
├── tools/
|
||||
│ └── database.py # SQLite database operations
|
||||
├── nodes.py # PocketFlow node implementation
|
||||
├── flow.py # Flow configuration
|
||||
└── main.py # Example usage
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
1. Create a virtual environment:
|
||||
```bash
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Run the example:
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Initialize a SQLite database with a tasks table
|
||||
2. Create an example task
|
||||
3. List all tasks in the database
|
||||
4. Display the results
|
||||
|
||||
## Key Concepts Demonstrated
|
||||
|
||||
1. **Database Operations**
|
||||
- Safe connection handling
|
||||
- Query parameterization
|
||||
- Schema management
|
||||
|
||||
2. **Code Organization**
|
||||
- Clear separation between database operations and PocketFlow components
|
||||
- Modular project structure
|
||||
- Type hints and documentation
|
||||
|
||||
3. **PocketFlow Integration**
|
||||
- Node implementation with prep->exec->post lifecycle
|
||||
- Flow configuration
|
||||
- Shared store usage for data passing
|
||||
|
||||
## Example Output
|
||||
|
||||
```
|
||||
Database Status: Database initialized
|
||||
Task Status: Task created successfully
|
||||
|
||||
All Tasks:
|
||||
- ID: 1
|
||||
Title: Example Task
|
||||
Description: This is an example task created using PocketFlow
|
||||
Status: pending
|
||||
Created: 2024-03-02 12:34:56
|
||||
```
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
from pocketflow import Flow
|
||||
from nodes import InitDatabaseNode, CreateTaskNode, ListTasksNode
|
||||
|
||||
def create_database_flow():
|
||||
"""Create a flow for database operations"""
|
||||
|
||||
# Create nodes
|
||||
init_db = InitDatabaseNode()
|
||||
create_task = CreateTaskNode()
|
||||
list_tasks = ListTasksNode()
|
||||
|
||||
# Connect nodes
|
||||
init_db >> create_task >> list_tasks
|
||||
|
||||
# Create and return flow
|
||||
return Flow(start=init_db)
|
||||
@@ -0,0 +1,29 @@
|
||||
from flow import create_database_flow
|
||||
|
||||
def main():
|
||||
# Create the flow
|
||||
flow = create_database_flow()
|
||||
|
||||
# Prepare example task data
|
||||
shared = {
|
||||
"task_title": "Example Task",
|
||||
"task_description": "This is an example task created using PocketFlow"
|
||||
}
|
||||
|
||||
# Run the flow
|
||||
flow.run(shared)
|
||||
|
||||
# Print results
|
||||
print("Database Status:", shared.get("db_status"))
|
||||
print("Task Status:", shared.get("task_status"))
|
||||
print("\nAll Tasks:")
|
||||
for task in shared.get("tasks", []):
|
||||
print(f"- ID: {task[0]}")
|
||||
print(f" Title: {task[1]}")
|
||||
print(f" Description: {task[2]}")
|
||||
print(f" Status: {task[3]}")
|
||||
print(f" Created: {task[4]}")
|
||||
print()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,43 @@
|
||||
from pocketflow import Node
|
||||
from tools.database import execute_sql, init_db
|
||||
|
||||
class InitDatabaseNode(Node):
|
||||
"""Node for initializing the database"""
|
||||
|
||||
def exec(self, _):
|
||||
init_db()
|
||||
return "Database initialized"
|
||||
|
||||
def post(self, shared, prep_res, exec_res):
|
||||
shared["db_status"] = exec_res
|
||||
return "default"
|
||||
|
||||
class CreateTaskNode(Node):
|
||||
"""Node for creating a new task"""
|
||||
|
||||
def prep(self, shared):
|
||||
return (
|
||||
shared.get("task_title", ""),
|
||||
shared.get("task_description", "")
|
||||
)
|
||||
|
||||
def exec(self, inputs):
|
||||
title, description = inputs
|
||||
query = "INSERT INTO tasks (title, description) VALUES (?, ?)"
|
||||
execute_sql(query, (title, description))
|
||||
return "Task created successfully"
|
||||
|
||||
def post(self, shared, prep_res, exec_res):
|
||||
shared["task_status"] = exec_res
|
||||
return "default"
|
||||
|
||||
class ListTasksNode(Node):
|
||||
"""Node for listing all tasks"""
|
||||
|
||||
def exec(self, _):
|
||||
query = "SELECT * FROM tasks"
|
||||
return execute_sql(query)
|
||||
|
||||
def post(self, shared, prep_res, exec_res):
|
||||
shared["tasks"] = exec_res
|
||||
return "default"
|
||||
@@ -0,0 +1,2 @@
|
||||
pocketflow>=0.1.0
|
||||
python-dotenv>=0.19.0
|
||||
@@ -0,0 +1,38 @@
|
||||
import sqlite3
|
||||
from typing import List, Tuple, Any
|
||||
|
||||
def execute_sql(query: str, params: Tuple = None) -> List[Tuple[Any, ...]]:
|
||||
"""Execute a SQL query and return results
|
||||
|
||||
Args:
|
||||
query (str): SQL query to execute
|
||||
params (tuple, optional): Query parameters to prevent SQL injection
|
||||
|
||||
Returns:
|
||||
list: Query results as a list of tuples
|
||||
"""
|
||||
conn = sqlite3.connect("example.db")
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
if params:
|
||||
cursor.execute(query, params)
|
||||
else:
|
||||
cursor.execute(query)
|
||||
result = cursor.fetchall()
|
||||
conn.commit()
|
||||
return result
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def init_db():
|
||||
"""Initialize database with example table"""
|
||||
create_table_sql = """
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
status TEXT DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
"""
|
||||
execute_sql(create_table_sql)
|
||||
Reference in New Issue
Block a user