Generate complete, production-ready functions and classes from formal specifications, design descriptions, type signatures, or natural language requirements. Use this skill when implementing APIs from specifications, creating data structures from schemas, building classes from UML diagrams, generating code from contracts, or translating design documents into code. Supports multiple programming languages and follows language-specific best practices.
Install with Tessl CLI
npx tessl i github:ArabelaTso/Skills-4-SE --skill function-class-generator75
Does it follow best practices?
If you maintain this skill, you can automatically optimize it using the tessl CLI to improve its score:
npx tessl skill review --optimize ./path/to/skillValidation for skill structure
Transform formal specifications, design descriptions, and requirements into complete, well-structured, production-ready code. Generates functions, classes, interfaces, and data structures with proper error handling, documentation, and tests.
Understand specifications from multiple sources:
Create complete implementations:
Apply language-specific patterns:
Ensure correctness:
Extract key information:
From type signature:
# Specification
def calculate_discount(price: float, percentage: float) -> float:
"""Calculate discounted price."""
passExtract:
calculate_discountprice (float), percentage (float)floatFrom formal specification:
Function: binary_search
Inputs: sorted_array: List[int], target: int
Output: int (index of target, or -1 if not found)
Preconditions:
- sorted_array is sorted in ascending order
- sorted_array is not empty
Postconditions:
- If result >= 0: sorted_array[result] == target
- If result == -1: target not in sorted_arrayPlan the structure:
Identify:
For binary_search example:
Create complete implementation:
Generated code:
def binary_search(sorted_array: list[int], target: int) -> int:
"""
Search for target in sorted array using binary search.
Args:
sorted_array: List of integers sorted in ascending order
target: Integer value to search for
Returns:
Index of target if found, -1 otherwise
Raises:
ValueError: If sorted_array is empty
TypeError: If inputs are not of correct type
Examples:
>>> binary_search([1, 2, 3, 4, 5], 3)
2
>>> binary_search([1, 2, 3, 4, 5], 6)
-1
Time Complexity: O(log n)
Space Complexity: O(1)
"""
if not isinstance(sorted_array, list):
raise TypeError("sorted_array must be a list")
if not isinstance(target, int):
raise TypeError("target must be an integer")
if not sorted_array:
raise ValueError("sorted_array cannot be empty")
left, right = 0, len(sorted_array) - 1
while left <= right:
mid = left + (right - left) // 2 # Avoid overflow
if sorted_array[mid] == target:
return mid
elif sorted_array[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1Include comprehensive documentation:
Elements:
Create validation tests:
import pytest
def test_binary_search_found():
"""Test finding an element in the middle."""
assert binary_search([1, 2, 3, 4, 5], 3) == 2
def test_binary_search_not_found():
"""Test element not in array."""
assert binary_search([1, 2, 3, 4, 5], 6) == -1
def test_binary_search_first_element():
"""Test finding first element."""
assert binary_search([1, 2, 3, 4, 5], 1) == 0
def test_binary_search_last_element():
"""Test finding last element."""
assert binary_search([1, 2, 3, 4, 5], 5) == 4
def test_binary_search_single_element_found():
"""Test single-element array with target present."""
assert binary_search([1], 1) == 0
def test_binary_search_single_element_not_found():
"""Test single-element array with target absent."""
assert binary_search([1], 2) == -1
def test_binary_search_empty_array():
"""Test that empty array raises ValueError."""
with pytest.raises(ValueError, match="cannot be empty"):
binary_search([], 1)
def test_binary_search_invalid_array_type():
"""Test that invalid array type raises TypeError."""
with pytest.raises(TypeError, match="must be a list"):
binary_search("not a list", 1)
def test_binary_search_invalid_target_type():
"""Test that invalid target type raises TypeError."""
with pytest.raises(TypeError, match="must be an integer"):
binary_search([1, 2, 3], "not an int")Specification:
function calculateArea(width: number, height: number): numberGenerated implementation:
/**
* Calculate the area of a rectangle.
*
* @param width - Width of the rectangle (must be positive)
* @param height - Height of the rectangle (must be positive)
* @returns The calculated area (width * height)
* @throws {Error} If width or height is not positive
*
* @example
* ```typescript
* calculateArea(5, 10) // returns 50
* calculateArea(2.5, 4) // returns 10
* ```
*/
function calculateArea(width: number, height: number): number {
if (width <= 0) {
throw new Error('Width must be positive');
}
if (height <= 0) {
throw new Error('Height must be positive');
}
return width * height;
}Generated tests:
import { describe, it, expect } from '@jest/globals';
describe('calculateArea', () => {
it('should calculate area correctly', () => {
expect(calculateArea(5, 10)).toBe(50);
expect(calculateArea(2.5, 4)).toBe(10);
});
it('should handle decimal values', () => {
expect(calculateArea(3.5, 2.5)).toBeCloseTo(8.75);
});
it('should throw error for zero width', () => {
expect(() => calculateArea(0, 10)).toThrow('Width must be positive');
});
it('should throw error for negative width', () => {
expect(() => calculateArea(-5, 10)).toThrow('Width must be positive');
});
it('should throw error for zero height', () => {
expect(() => calculateArea(10, 0)).toThrow('Height must be positive');
});
it('should throw error for negative height', () => {
expect(() => calculateArea(10, -5)).toThrow('Height must be positive');
});
});Specification:
Class: BankAccount
Purpose: Manage a bank account with deposits and withdrawals
Attributes:
- account_number: string (unique identifier)
- balance: decimal (current balance, must be >= 0)
- owner_name: string
Methods:
- deposit(amount): Add money to account
Precondition: amount > 0
Postcondition: balance increased by amount
- withdraw(amount): Remove money from account
Precondition: amount > 0 and amount <= balance
Postcondition: balance decreased by amount
- get_balance(): Return current balance
Postcondition: returns balance >= 0
Invariants:
- balance must always be >= 0
- account_number is immutableGenerated implementation:
from decimal import Decimal
from typing import Final
class InsufficientFundsError(Exception):
"""Raised when withdrawal amount exceeds account balance."""
pass
class InvalidAmountError(Exception):
"""Raised when transaction amount is invalid."""
pass
class BankAccount:
"""
Manage a bank account with deposits and withdrawals.
Invariants:
- Balance is always >= 0
- Account number is immutable once set
Attributes:
account_number: Unique account identifier (immutable)
balance: Current account balance (non-negative)
owner_name: Name of account owner
"""
def __init__(self, account_number: str, owner_name: str, initial_balance: Decimal = Decimal('0')):
"""
Initialize a new bank account.
Args:
account_number: Unique account identifier
owner_name: Name of account owner
initial_balance: Starting balance (default: 0)
Raises:
ValueError: If account_number or owner_name is empty
InvalidAmountError: If initial_balance is negative
"""
if not account_number:
raise ValueError("Account number cannot be empty")
if not owner_name:
raise ValueError("Owner name cannot be empty")
if initial_balance < 0:
raise InvalidAmountError("Initial balance cannot be negative")
self._account_number: Final[str] = account_number
self._balance: Decimal = initial_balance
self.owner_name: str = owner_name
@property
def account_number(self) -> str:
"""Get account number (immutable)."""
return self._account_number
@property
def balance(self) -> Decimal:
"""Get current account balance."""
return self._balance
def deposit(self, amount: Decimal) -> None:
"""
Add money to the account.
Args:
amount: Amount to deposit (must be positive)
Raises:
InvalidAmountError: If amount is not positive
Postcondition:
Balance increases by amount
"""
if amount <= 0:
raise InvalidAmountError("Deposit amount must be positive")
self._balance += amount
def withdraw(self, amount: Decimal) -> None:
"""
Remove money from the account.
Args:
amount: Amount to withdraw (must be positive and <= balance)
Raises:
InvalidAmountError: If amount is not positive
InsufficientFundsError: If amount exceeds current balance
Postcondition:
Balance decreases by amount
"""
if amount <= 0:
raise InvalidAmountError("Withdrawal amount must be positive")
if amount > self._balance:
raise InsufficientFundsError(
f"Insufficient funds: balance={self._balance}, requested={amount}"
)
self._balance -= amount
def get_balance(self) -> Decimal:
"""
Return current account balance.
Returns:
Current balance (always >= 0)
"""
return self._balance
def __repr__(self) -> str:
"""Return string representation of account."""
return f"BankAccount(account_number={self._account_number!r}, balance={self._balance}, owner={self.owner_name!r})"Generated tests:
import pytest
from decimal import Decimal
class TestBankAccount:
"""Test suite for BankAccount class."""
def test_init_valid(self):
"""Test creating account with valid parameters."""
account = BankAccount("12345", "John Doe", Decimal('100'))
assert account.account_number == "12345"
assert account.balance == Decimal('100')
assert account.owner_name == "John Doe"
def test_init_default_balance(self):
"""Test creating account with default zero balance."""
account = BankAccount("12345", "John Doe")
assert account.balance == Decimal('0')
def test_init_invalid_account_number(self):
"""Test that empty account number raises ValueError."""
with pytest.raises(ValueError, match="Account number cannot be empty"):
BankAccount("", "John Doe")
def test_init_invalid_owner_name(self):
"""Test that empty owner name raises ValueError."""
with pytest.raises(ValueError, match="Owner name cannot be empty"):
BankAccount("12345", "")
def test_init_negative_balance(self):
"""Test that negative initial balance raises InvalidAmountError."""
with pytest.raises(InvalidAmountError, match="cannot be negative"):
BankAccount("12345", "John Doe", Decimal('-10'))
def test_account_number_immutable(self):
"""Test that account number cannot be changed."""
account = BankAccount("12345", "John Doe")
with pytest.raises(AttributeError):
account.account_number = "67890"
def test_deposit_valid(self):
"""Test depositing positive amount."""
account = BankAccount("12345", "John Doe", Decimal('100'))
account.deposit(Decimal('50'))
assert account.balance == Decimal('150')
def test_deposit_zero(self):
"""Test that depositing zero raises InvalidAmountError."""
account = BankAccount("12345", "John Doe")
with pytest.raises(InvalidAmountError, match="must be positive"):
account.deposit(Decimal('0'))
def test_deposit_negative(self):
"""Test that depositing negative amount raises InvalidAmountError."""
account = BankAccount("12345", "John Doe")
with pytest.raises(InvalidAmountError, match="must be positive"):
account.deposit(Decimal('-10'))
def test_withdraw_valid(self):
"""Test withdrawing valid amount."""
account = BankAccount("12345", "John Doe", Decimal('100'))
account.withdraw(Decimal('30'))
assert account.balance == Decimal('70')
def test_withdraw_entire_balance(self):
"""Test withdrawing entire balance."""
account = BankAccount("12345", "John Doe", Decimal('100'))
account.withdraw(Decimal('100'))
assert account.balance == Decimal('0')
def test_withdraw_insufficient_funds(self):
"""Test that withdrawing more than balance raises InsufficientFundsError."""
account = BankAccount("12345", "John Doe", Decimal('100'))
with pytest.raises(InsufficientFundsError, match="Insufficient funds"):
account.withdraw(Decimal('150'))
def test_withdraw_zero(self):
"""Test that withdrawing zero raises InvalidAmountError."""
account = BankAccount("12345", "John Doe", Decimal('100'))
with pytest.raises(InvalidAmountError, match="must be positive"):
account.withdraw(Decimal('0'))
def test_withdraw_negative(self):
"""Test that withdrawing negative amount raises InvalidAmountError."""
account = BankAccount("12345", "John Doe", Decimal('100'))
with pytest.raises(InvalidAmountError, match="must be positive"):
account.withdraw(Decimal('-10'))
def test_get_balance(self):
"""Test getting account balance."""
account = BankAccount("12345", "John Doe", Decimal('100'))
assert account.get_balance() == Decimal('100')
assert account.get_balance() >= 0 # Invariant check
def test_multiple_transactions(self):
"""Test sequence of deposits and withdrawals."""
account = BankAccount("12345", "John Doe", Decimal('100'))
account.deposit(Decimal('50')) # 150
account.withdraw(Decimal('30')) # 120
account.deposit(Decimal('10')) # 130
account.withdraw(Decimal('80')) # 50
assert account.balance == Decimal('50')
def test_repr(self):
"""Test string representation."""
account = BankAccount("12345", "John Doe", Decimal('100'))
repr_str = repr(account)
assert "12345" in repr_str
assert "John Doe" in repr_str
assert "100" in repr_strSpecification (OpenAPI):
paths:
/users/{userId}:
get:
summary: Get user by ID
parameters:
- name: userId
in: path
required: true
schema:
type: integer
responses:
'200':
description: User found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: User not foundGenerated implementation (Python with FastAPI):
from fastapi import FastAPI, HTTPException, Path
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class User(BaseModel):
"""User model."""
id: int
name: str
email: str
created_at: str
class Config:
json_schema_extra = {
"example": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"created_at": "2024-01-01T00:00:00Z"
}
}
# Mock database
users_db: dict[int, User] = {
1: User(id=1, name="John Doe", email="john@example.com", created_at="2024-01-01T00:00:00Z")
}
@app.get(
"/users/{userId}",
response_model=User,
summary="Get user by ID",
responses={
200: {"description": "User found"},
404: {"description": "User not found"}
}
)
async def get_user(
userId: int = Path(..., description="User ID", ge=1)
) -> User:
"""
Retrieve a user by their ID.
Args:
userId: Unique user identifier (must be >= 1)
Returns:
User object with id, name, email, and created_at
Raises:
HTTPException: 404 if user not found
"""
user = users_db.get(userId)
if user is None:
raise HTTPException(status_code=404, detail=f"User {userId} not found")
return userGenerated tests:
from fastapi.testclient import TestClient
import pytest
client = TestClient(app)
def test_get_user_success():
"""Test retrieving existing user."""
response = client.get("/users/1")
assert response.status_code == 200
data = response.json()
assert data["id"] == 1
assert data["name"] == "John Doe"
assert data["email"] == "john@example.com"
def test_get_user_not_found():
"""Test retrieving non-existent user."""
response = client.get("/users/999")
assert response.status_code == 404
assert "not found" in response.json()["detail"].lower()
def test_get_user_invalid_id():
"""Test with invalid user ID."""
response = client.get("/users/0")
assert response.status_code == 422 # Validation error
def test_get_user_negative_id():
"""Test with negative user ID."""
response = client.get("/users/-1")
assert response.status_code == 422 # Validation errorSpecification (JSON Schema):
{
"type": "object",
"title": "Product",
"required": ["id", "name", "price"],
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"price": {
"type": "number",
"minimum": 0
},
"category": {
"type": "string",
"enum": ["electronics", "clothing", "food", "other"]
},
"inStock": {
"type": "boolean",
"default": true
}
}
}Generated implementation (TypeScript):
/**
* Product category enumeration.
*/
export enum ProductCategory {
Electronics = 'electronics',
Clothing = 'clothing',
Food = 'food',
Other = 'other'
}
/**
* Product data structure.
*/
export interface Product {
/** Unique product identifier (must be >= 1) */
id: number;
/** Product name (1-100 characters) */
name: string;
/** Product price (must be >= 0) */
price: number;
/** Product category (optional) */
category?: ProductCategory;
/** Whether product is in stock (default: true) */
inStock?: boolean;
}
/**
* Validate a product object.
*
* @param product - Product object to validate
* @throws {Error} If validation fails
*/
export function validateProduct(product: Product): void {
if (product.id < 1) {
throw new Error('Product ID must be at least 1');
}
if (product.name.length < 1 || product.name.length > 100) {
throw new Error('Product name must be 1-100 characters');
}
if (product.price < 0) {
throw new Error('Product price must be non-negative');
}
if (product.category !== undefined &&
!Object.values(ProductCategory).includes(product.category)) {
throw new Error(`Invalid category: ${product.category}`);
}
}
/**
* Create a product with validation.
*
* @param data - Product data
* @returns Validated product object
* @throws {Error} If validation fails
*/
export function createProduct(data: Product): Product {
const product: Product = {
id: data.id,
name: data.name,
price: data.price,
category: data.category,
inStock: data.inStock ?? true
};
validateProduct(product);
return product;
}Generated tests:
import { describe, it, expect } from '@jest/globals';
import { Product, ProductCategory, validateProduct, createProduct } from './product';
describe('Product validation', () => {
const validProduct: Product = {
id: 1,
name: 'Test Product',
price: 10.99,
category: ProductCategory.Electronics,
inStock: true
};
describe('validateProduct', () => {
it('should accept valid product', () => {
expect(() => validateProduct(validProduct)).not.toThrow();
});
it('should reject product with invalid ID', () => {
const invalid = { ...validProduct, id: 0 };
expect(() => validateProduct(invalid)).toThrow('ID must be at least 1');
});
it('should reject product with empty name', () => {
const invalid = { ...validProduct, name: '' };
expect(() => validateProduct(invalid)).toThrow('name must be 1-100 characters');
});
it('should reject product with too long name', () => {
const invalid = { ...validProduct, name: 'a'.repeat(101) };
expect(() => validateProduct(invalid)).toThrow('name must be 1-100 characters');
});
it('should reject product with negative price', () => {
const invalid = { ...validProduct, price: -1 };
expect(() => validateProduct(invalid)).toThrow('price must be non-negative');
});
it('should accept product with zero price', () => {
const valid = { ...validProduct, price: 0 };
expect(() => validateProduct(valid)).not.toThrow();
});
it('should accept product without category', () => {
const valid = { ...validProduct, category: undefined };
expect(() => validateProduct(valid)).not.toThrow();
});
});
describe('createProduct', () => {
it('should create product with all fields', () => {
const product = createProduct(validProduct);
expect(product).toEqual(validProduct);
});
it('should set default inStock to true', () => {
const data = { ...validProduct, inStock: undefined };
const product = createProduct(data);
expect(product.inStock).toBe(true);
});
it('should respect explicit inStock value', () => {
const data = { ...validProduct, inStock: false };
const product = createProduct(data);
expect(product.inStock).toBe(false);
});
it('should throw on invalid data', () => {
const invalid = { ...validProduct, id: -1 };
expect(() => createProduct(invalid)).toThrow();
});
});
});c1fb172
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.