forked from cleveragents/cleveragents-core
3c0b326c0d
Each simulation ran the full legacy lifecycle (init → tell → build → apply) with real Anthropic Claude API calls: 1. sim1-todo-cli: Click-based todo app (add/list/delete) 2. sim2-bookstore-api: FastAPI CRUD with SQLite (5 code files) 3. sim3-websocket-chat: async websocket chat server 4. sim4-hn-scraper: HN top stories scraper with JSON output 5. sim5-flask-auth: Flask + Flask-Login authentication app All 5 generated correct, production-quality Python code matching the requested task specifications.
316 lines
7.4 KiB
Python
316 lines
7.4 KiB
Python
I'll create a production-ready CLI todo application using Click. Here's the complete implementation:
|
||
|
||
## `todo.py`
|
||
```python
|
||
#!/usr/bin/env python3
|
||
"""
|
||
A simple CLI todo application built with Click.
|
||
"""
|
||
import json
|
||
import click
|
||
from pathlib import Path
|
||
from datetime import datetime
|
||
from typing import List, Dict, Any
|
||
import sys
|
||
|
||
|
||
class TodoManager:
|
||
"""Manages todo items with JSON file persistence."""
|
||
|
||
def __init__(self, data_file: str = "todos.json"):
|
||
self.data_file = Path(data_file)
|
||
self._ensure_data_file()
|
||
|
||
def _ensure_data_file(self) -> None:
|
||
"""Create data file if it doesn't exist."""
|
||
if not self.data_file.exists():
|
||
self._save_todos([])
|
||
|
||
def _load_todos(self) -> List[Dict[str, Any]]:
|
||
"""Load todos from JSON file."""
|
||
try:
|
||
with open(self.data_file, 'r', encoding='utf-8') as f:
|
||
return json.load(f)
|
||
except (json.JSONDecodeError, FileNotFoundError) as e:
|
||
click.echo(f"Error reading todos: {e}", err=True)
|
||
return []
|
||
|
||
def _save_todos(self, todos: List[Dict[str, Any]]) -> None:
|
||
"""Save todos to JSON file."""
|
||
try:
|
||
with open(self.data_file, 'w', encoding='utf-8') as f:
|
||
json.dump(todos, f, indent=2, ensure_ascii=False)
|
||
except IOError as e:
|
||
click.echo(f"Error saving todos: {e}", err=True)
|
||
sys.exit(1)
|
||
|
||
def add_todo(self, text: str) -> int:
|
||
"""Add a new todo item and return its ID."""
|
||
todos = self._load_todos()
|
||
todo_id = max([todo.get('id', 0) for todo in todos], default=0) + 1
|
||
|
||
new_todo = {
|
||
'id': todo_id,
|
||
'text': text.strip(),
|
||
'created': datetime.now().isoformat(),
|
||
'completed': False
|
||
}
|
||
|
||
todos.append(new_todo)
|
||
self._save_todos(todos)
|
||
return todo_id
|
||
|
||
def list_todos(self) -> List[Dict[str, Any]]:
|
||
"""Get all todo items."""
|
||
return self._load_todos()
|
||
|
||
def delete_todo(self, todo_id: int) -> bool:
|
||
"""Delete a todo item by ID. Returns True if deleted, False if not found."""
|
||
todos = self._load_todos()
|
||
original_length = len(todos)
|
||
todos = [todo for todo in todos if todo.get('id') != todo_id]
|
||
|
||
if len(todos) < original_length:
|
||
self._save_todos(todos)
|
||
return True
|
||
return False
|
||
|
||
|
||
# Global todo manager instance
|
||
todo_manager = TodoManager()
|
||
|
||
|
||
@click.group()
|
||
@click.version_option(version="1.0.0")
|
||
def cli():
|
||
"""A simple CLI todo application.
|
||
|
||
Manage your todo items with add, list, and delete commands.
|
||
"""
|
||
pass
|
||
|
||
|
||
@cli.command()
|
||
@click.argument('text', required=True)
|
||
def add(text: str):
|
||
"""Add a new todo item.
|
||
|
||
TEXT: The todo item description
|
||
|
||
Example: todo add "Buy groceries"
|
||
"""
|
||
if not text.strip():
|
||
click.echo("Error: Todo text cannot be empty", err=True)
|
||
sys.exit(1)
|
||
|
||
todo_id = todo_manager.add_todo(text)
|
||
click.echo(f"✅ Added todo #{todo_id}: {text}")
|
||
|
||
|
||
@cli.command()
|
||
@click.option('--show-ids', is_flag=True, help='Show todo IDs for deletion')
|
||
def list(show_ids: bool):
|
||
"""List all todo items.
|
||
|
||
Use --show-ids to display IDs for deletion.
|
||
|
||
Example: todo list --show-ids
|
||
"""
|
||
todos = todo_manager.list_todos()
|
||
|
||
if not todos:
|
||
click.echo("📝 No todos found. Add some with 'todo add <text>'")
|
||
return
|
||
|
||
click.echo(f"📋 You have {len(todos)} todo(s):\n")
|
||
|
||
for todo in todos:
|
||
status = "✅" if todo.get('completed') else "⏳"
|
||
text = todo.get('text', '')
|
||
|
||
if show_ids:
|
||
click.echo(f" {status} #{todo.get('id')}: {text}")
|
||
else:
|
||
click.echo(f" {status} {text}")
|
||
|
||
|
||
@cli.command()
|
||
@click.argument('todo_id', type=int)
|
||
@click.confirmation_option(prompt='Are you sure you want to delete this todo?')
|
||
def delete(todo_id: int):
|
||
"""Delete a todo item by ID.
|
||
|
||
TODO_ID: The ID of the todo item to delete (use 'todo list --show-ids' to see IDs)
|
||
|
||
Example: todo delete 1
|
||
"""
|
||
if todo_manager.delete_todo(todo_id):
|
||
click.echo(f"🗑️ Deleted todo #{todo_id}")
|
||
else:
|
||
click.echo(f"❌ Todo #{todo_id} not found", err=True)
|
||
sys.exit(1)
|
||
|
||
|
||
if __name__ == '__main__':
|
||
cli()
|
||
```
|
||
|
||
## `requirements.txt`
|
||
```txt
|
||
click>=8.0.0
|
||
```
|
||
|
||
## `setup.py`
|
||
```python
|
||
from setuptools import setup, find_packages
|
||
|
||
setup(
|
||
name='todo-cli',
|
||
version='1.0.0',
|
||
py_modules=['todo'],
|
||
install_requires=[
|
||
'click>=8.0.0',
|
||
],
|
||
entry_points={
|
||
'console_scripts': [
|
||
'todo=todo:cli',
|
||
],
|
||
},
|
||
author='Your Name',
|
||
author_email='your.email@example.com',
|
||
description='A simple CLI todo application',
|
||
long_description=open('README.md').read(),
|
||
long_description_content_type='text/markdown',
|
||
url='https://github.com/yourusername/todo-cli',
|
||
classifiers=[
|
||
'Development Status :: 4 - Beta',
|
||
'Intended Audience :: Developers',
|
||
'License :: OSI Approved :: MIT License',
|
||
'Programming Language :: Python :: 3',
|
||
'Programming Language :: Python :: 3.7+',
|
||
],
|
||
python_requires='>=3.7',
|
||
)
|
||
```
|
||
|
||
## `README.md`
|
||
```markdown
|
||
# Todo CLI
|
||
|
||
A simple command-line todo application built with Python and Click.
|
||
|
||
## Features
|
||
|
||
- ✅ Add new todo items
|
||
- 📋 List all todos with optional IDs
|
||
- 🗑️ Delete todos by ID
|
||
- 💾 Persistent storage using JSON
|
||
- 🎨 Colorful CLI interface with emojis
|
||
|
||
## Installation
|
||
|
||
### Option 1: Install as a package
|
||
```bash
|
||
pip install -e .
|
||
todo --help
|
||
```
|
||
|
||
### Option 2: Run directly
|
||
```bash
|
||
pip install -r requirements.txt
|
||
python todo.py --help
|
||
```
|
||
|
||
## Usage
|
||
|
||
### Add a todo
|
||
```bash
|
||
todo add "Buy groceries"
|
||
todo add "Finish project documentation"
|
||
```
|
||
|
||
### List todos
|
||
```bash
|
||
# Simple list
|
||
todo list
|
||
|
||
# List with IDs (needed for deletion)
|
||
todo list --show-ids
|
||
```
|
||
|
||
### Delete a todo
|
||
```bash
|
||
# First, get the ID with --show-ids
|
||
todo list --show-ids
|
||
|
||
# Then delete by ID
|
||
todo delete 1
|
||
```
|
||
|
||
### Get help
|
||
```bash
|
||
todo --help
|
||
todo add --help
|
||
todo list --help
|
||
todo delete --help
|
||
```
|
||
|
||
## Data Storage
|
||
|
||
Todos are stored in a `todos.json` file in the current directory. The file is automatically created when you add your first todo.
|
||
|
||
## Example Session
|
||
|
||
```bash
|
||
$ todo add "Learn Python"
|
||
✅ Added todo #1: Learn Python
|
||
|
||
$ todo add "Build a CLI app"
|
||
✅ Added todo #2: Build a CLI app
|
||
|
||
$ todo list --show-ids
|
||
📋 You have 2 todo(s):
|
||
|
||
⏳ #1: Learn Python
|
||
⏳ #2: Build a CLI app
|
||
|
||
$ todo delete 1
|
||
Are you sure you want to delete this todo? [y/N]: y
|
||
🗑️ Deleted todo #1
|
||
|
||
$ todo list
|
||
📋 You have 1 todo(s):
|
||
|
||
⏳ Build a CLI app
|
||
```
|
||
|
||
## Requirements
|
||
|
||
- Python 3.7+
|
||
- Click 8.0+
|
||
|
||
## License
|
||
|
||
MIT License
|
||
```
|
||
|
||
## Key Features
|
||
|
||
1. **Production-ready**: Error handling, input validation, and proper exit codes
|
||
2. **User-friendly**: Confirmation prompts, helpful messages, and emoji indicators
|
||
3. **Robust storage**: JSON persistence with proper file handling
|
||
4. **Flexible installation**: Can be installed as a package or run directly
|
||
5. **Good UX**: Clear help messages, optional ID display, and status indicators
|
||
6. **Cross-platform**: Uses `pathlib` for proper file handling
|
||
|
||
## Usage Examples
|
||
|
||
```bash
|
||
# Install and run
|
||
pip install -r requirements.txt
|
||
python todo.py add "My first todo"
|
||
python todo.py list --show-ids
|
||
python todo.py delete 1
|
||
```
|
||
|
||
The application handles edge cases like empty todos, missing files, and invalid IDs gracefully with appropriate error messages. |