Transform repository into a plugin marketplace structure with two plugins: - claude-code plugin: Complete toolkit with 5 skills * claude-code-plugins * claude-code-slash-commands * claude-code-hooks * claude-code-subagents * claude-code-memory - claude-skills plugin: Meta-skill for creating Agent Skills * Comprehensive best practices guide * Templates and examples * Progressive disclosure patterns Infrastructure: - Add marketplace.json manifest - Create plugin.json for each plugin - Update documentation for marketplace structure - Add contribution and testing guides Installation: - /plugin install claude-code@claude-skills - /plugin install claude-skills@claude-skills 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
904 lines
22 KiB
Markdown
904 lines
22 KiB
Markdown
# Skill Examples
|
|
|
|
This file contains complete, working examples of well-structured skills across different domains.
|
|
|
|
## Example 1: Python Testing Skill
|
|
|
|
### Structure
|
|
```
|
|
python-testing-skill/
|
|
├── SKILL.md
|
|
└── test-templates/
|
|
├── pytest-basic.py
|
|
└── pytest-advanced.py
|
|
```
|
|
|
|
### SKILL.md
|
|
```markdown
|
|
---
|
|
name: Python Testing with pytest
|
|
description: Create comprehensive Python tests using pytest with fixtures, parametrization, and mocking. Use when writing unit tests, integration tests, or setting up test infrastructure for Python projects.
|
|
---
|
|
|
|
## When to Use This Skill
|
|
|
|
Use this skill when:
|
|
- Writing unit tests for Python functions and classes
|
|
- Creating integration tests for Python applications
|
|
- Setting up pytest configuration and fixtures
|
|
- Implementing test parametrization for multiple scenarios
|
|
- Mocking external dependencies in tests
|
|
|
|
Do NOT use this skill for:
|
|
- Testing non-Python code
|
|
- End-to-end browser testing (use Playwright skill instead)
|
|
- Load testing or performance benchmarking
|
|
|
|
## Quick Start
|
|
|
|
Basic test structure:
|
|
|
|
```python
|
|
import pytest
|
|
from myapp import add_numbers
|
|
|
|
def test_add_numbers():
|
|
result = add_numbers(2, 3)
|
|
assert result == 5
|
|
```
|
|
|
|
Run tests:
|
|
```bash
|
|
pytest tests/ -v
|
|
```
|
|
|
|
## Core Workflows
|
|
|
|
### Workflow 1: Writing Unit Tests
|
|
|
|
1. Create a test file matching your source file: `test_module.py` for `module.py`
|
|
2. Import the code to test and pytest
|
|
3. Write test functions starting with `test_`
|
|
4. Use assert statements for validation
|
|
5. Run pytest from project root
|
|
|
|
**Example:**
|
|
```python
|
|
# test_calculator.py
|
|
import pytest
|
|
from calculator import Calculator
|
|
|
|
def test_addition():
|
|
calc = Calculator()
|
|
assert calc.add(2, 3) == 5
|
|
assert calc.add(-1, 1) == 0
|
|
assert calc.add(0, 0) == 0
|
|
|
|
def test_division_by_zero():
|
|
calc = Calculator()
|
|
with pytest.raises(ValueError, match="Cannot divide by zero"):
|
|
calc.divide(10, 0)
|
|
```
|
|
|
|
### Workflow 2: Using Fixtures
|
|
|
|
1. Create fixtures for common test setup
|
|
2. Use `@pytest.fixture` decorator
|
|
3. Accept fixtures as test function parameters
|
|
4. Fixtures run automatically before tests
|
|
|
|
**Example:**
|
|
```python
|
|
import pytest
|
|
from database import Database
|
|
|
|
@pytest.fixture
|
|
def db():
|
|
"""Provide a test database instance"""
|
|
database = Database(":memory:")
|
|
database.setup()
|
|
yield database
|
|
database.teardown()
|
|
|
|
def test_create_user(db):
|
|
user = db.create_user("alice", "alice@example.com")
|
|
assert user.name == "alice"
|
|
assert user.email == "alice@example.com"
|
|
|
|
def test_query_user(db):
|
|
db.create_user("bob", "bob@example.com")
|
|
user = db.query_user("bob")
|
|
assert user is not None
|
|
```
|
|
|
|
### Workflow 3: Parametrized Tests
|
|
|
|
1. Use `@pytest.mark.parametrize` decorator
|
|
2. Provide parameter names and test cases
|
|
3. Test function runs once per parameter set
|
|
|
|
**Example:**
|
|
```python
|
|
import pytest
|
|
from validators import validate_email
|
|
|
|
@pytest.mark.parametrize("email,expected", [
|
|
("user@example.com", True),
|
|
("user@domain.co.uk", True),
|
|
("invalid@", False),
|
|
("@example.com", False),
|
|
("no-at-sign.com", False),
|
|
("", False),
|
|
])
|
|
def test_email_validation(email, expected):
|
|
assert validate_email(email) == expected
|
|
```
|
|
|
|
### Workflow 4: Mocking External Dependencies
|
|
|
|
1. Import `unittest.mock` or use `pytest-mock`
|
|
2. Use `mocker.patch()` to replace dependencies
|
|
3. Configure mock return values or side effects
|
|
4. Verify mock interactions
|
|
|
|
**Example:**
|
|
```python
|
|
import pytest
|
|
from unittest.mock import Mock
|
|
from weather_app import get_weather
|
|
|
|
def test_get_weather(mocker):
|
|
# Mock the external API call
|
|
mock_api = mocker.patch('weather_app.weather_api.fetch')
|
|
mock_api.return_value = {
|
|
"temperature": 72,
|
|
"conditions": "sunny"
|
|
}
|
|
|
|
result = get_weather("San Francisco")
|
|
|
|
assert result["temperature"] == 72
|
|
assert result["conditions"] == "sunny"
|
|
mock_api.assert_called_once_with("San Francisco")
|
|
```
|
|
|
|
## Test Organization
|
|
|
|
### Project Structure
|
|
```
|
|
myproject/
|
|
├── src/
|
|
│ └── myapp/
|
|
│ ├── __init__.py
|
|
│ ├── core.py
|
|
│ └── utils.py
|
|
├── tests/
|
|
│ ├── __init__.py
|
|
│ ├── conftest.py # Shared fixtures
|
|
│ ├── test_core.py
|
|
│ └── test_utils.py
|
|
└── pyproject.toml # pytest configuration
|
|
```
|
|
|
|
### conftest.py for Shared Fixtures
|
|
```python
|
|
import pytest
|
|
from myapp import create_app
|
|
|
|
@pytest.fixture(scope="session")
|
|
def app():
|
|
"""Create application for testing"""
|
|
app = create_app(testing=True)
|
|
return app
|
|
|
|
@pytest.fixture
|
|
def client(app):
|
|
"""Test client for making requests"""
|
|
return app.test_client()
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### pyproject.toml
|
|
```toml
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
python_files = ["test_*.py"]
|
|
python_functions = ["test_*"]
|
|
addopts = [
|
|
"-v",
|
|
"--strict-markers",
|
|
"--cov=myapp",
|
|
"--cov-report=term-missing",
|
|
]
|
|
markers = [
|
|
"slow: marks tests as slow",
|
|
"integration: marks tests as integration tests",
|
|
]
|
|
```
|
|
|
|
## Coverage Goals
|
|
|
|
Aim for:
|
|
- 80%+ code coverage for business logic
|
|
- 100% coverage for critical paths (auth, payments, data integrity)
|
|
- Edge cases and error conditions tested
|
|
- Integration tests for key workflows
|
|
|
|
Check coverage:
|
|
```bash
|
|
pytest --cov=myapp --cov-report=html
|
|
open htmlcov/index.html
|
|
```
|
|
|
|
## Common Pitfalls
|
|
|
|
### Issue: Tests Pass Locally but Fail in CI
|
|
**Solution:**
|
|
- Use fixtures to avoid state pollution between tests
|
|
- Don't rely on file system state or specific paths
|
|
- Mock time-dependent functionality
|
|
- Set explicit random seeds for reproducibility
|
|
|
|
### Issue: Slow Test Suite
|
|
**Solution:**
|
|
- Use `@pytest.mark.slow` for slow tests, run separately
|
|
- Mock external API calls instead of making real requests
|
|
- Use in-memory databases for tests
|
|
- Run fast unit tests before slow integration tests
|
|
|
|
### Issue: Fixtures Not Running
|
|
**Solution:**
|
|
- Ensure fixture name matches parameter name exactly
|
|
- Check fixture scope (function/class/module/session)
|
|
- Verify conftest.py is in correct location
|
|
|
|
## Advanced Techniques
|
|
|
|
### Async Testing
|
|
```python
|
|
import pytest
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_async_function():
|
|
result = await async_fetch_data()
|
|
assert result["status"] == "success"
|
|
```
|
|
|
|
### Testing Exceptions with Context
|
|
```python
|
|
def test_invalid_input():
|
|
with pytest.raises(ValueError) as exc_info:
|
|
process_data(invalid_input)
|
|
assert "expected format" in str(exc_info.value)
|
|
```
|
|
|
|
### Temporary File Testing
|
|
```python
|
|
def test_file_processing(tmp_path):
|
|
# tmp_path is a pytest fixture providing a temporary directory
|
|
test_file = tmp_path / "test.txt"
|
|
test_file.write_text("test content")
|
|
|
|
result = process_file(test_file)
|
|
assert result.success
|
|
```
|
|
```
|
|
|
|
---
|
|
|
|
## Example 2: API Integration Skill
|
|
|
|
### SKILL.md
|
|
```markdown
|
|
---
|
|
name: REST API Integration
|
|
description: Design and implement RESTful API integrations with proper error handling, authentication, and rate limiting. Use when building API clients or integrating third-party services.
|
|
---
|
|
|
|
## When to Use This Skill
|
|
|
|
Use this skill when:
|
|
- Integrating third-party REST APIs into your application
|
|
- Building API client libraries
|
|
- Implementing API authentication flows (OAuth, JWT, API keys)
|
|
- Handling rate limiting and retries
|
|
- Creating robust error handling for API calls
|
|
|
|
Do NOT use this skill for:
|
|
- GraphQL APIs (different query paradigm)
|
|
- gRPC or WebSocket connections
|
|
- Building API servers (use framework-specific skills)
|
|
|
|
## Quick Start
|
|
|
|
Basic API client structure:
|
|
|
|
```python
|
|
import requests
|
|
|
|
class APIClient:
|
|
def __init__(self, base_url, api_key):
|
|
self.base_url = base_url
|
|
self.session = requests.Session()
|
|
self.session.headers.update({
|
|
"Authorization": f"Bearer {api_key}",
|
|
"Content-Type": "application/json"
|
|
})
|
|
|
|
def get(self, endpoint):
|
|
response = self.session.get(f"{self.base_url}{endpoint}")
|
|
response.raise_for_status()
|
|
return response.json()
|
|
```
|
|
|
|
## Core Workflows
|
|
|
|
### Workflow 1: Implementing Authentication
|
|
|
|
**API Key Authentication:**
|
|
```python
|
|
class APIKeyClient:
|
|
def __init__(self, api_key):
|
|
self.headers = {"X-API-Key": api_key}
|
|
|
|
def request(self, method, url, **kwargs):
|
|
kwargs.setdefault('headers', {}).update(self.headers)
|
|
return requests.request(method, url, **kwargs)
|
|
```
|
|
|
|
**OAuth 2.0 Flow:**
|
|
```python
|
|
from requests_oauthlib import OAuth2Session
|
|
|
|
class OAuthClient:
|
|
def __init__(self, client_id, client_secret, redirect_uri):
|
|
self.client_id = client_id
|
|
self.client_secret = client_secret
|
|
self.redirect_uri = redirect_uri
|
|
self.session = None
|
|
|
|
def get_authorization_url(self, authorization_base_url):
|
|
oauth = OAuth2Session(self.client_id, redirect_uri=self.redirect_uri)
|
|
authorization_url, state = oauth.authorization_url(authorization_base_url)
|
|
return authorization_url, state
|
|
|
|
def fetch_token(self, token_url, authorization_response):
|
|
oauth = OAuth2Session(self.client_id, redirect_uri=self.redirect_uri)
|
|
token = oauth.fetch_token(
|
|
token_url,
|
|
authorization_response=authorization_response,
|
|
client_secret=self.client_secret
|
|
)
|
|
self.session = oauth
|
|
return token
|
|
```
|
|
|
|
### Workflow 2: Error Handling and Retries
|
|
|
|
```python
|
|
import time
|
|
from requests.adapters import HTTPAdapter
|
|
from requests.packages.urllib3.util.retry import Retry
|
|
|
|
class RobustAPIClient:
|
|
def __init__(self, base_url, api_key, max_retries=3):
|
|
self.base_url = base_url
|
|
self.session = requests.Session()
|
|
|
|
# Configure retry strategy
|
|
retry_strategy = Retry(
|
|
total=max_retries,
|
|
backoff_factor=1,
|
|
status_forcelist=[429, 500, 502, 503, 504],
|
|
allowed_methods=["GET", "POST", "PUT", "DELETE"]
|
|
)
|
|
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
self.session.mount("http://", adapter)
|
|
self.session.mount("https://", adapter)
|
|
|
|
self.session.headers.update({
|
|
"Authorization": f"Bearer {api_key}"
|
|
})
|
|
|
|
def request(self, method, endpoint, **kwargs):
|
|
url = f"{self.base_url}{endpoint}"
|
|
try:
|
|
response = self.session.request(method, url, **kwargs)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except requests.exceptions.HTTPError as e:
|
|
if e.response.status_code == 401:
|
|
raise AuthenticationError("Invalid or expired API key")
|
|
elif e.response.status_code == 404:
|
|
raise NotFoundError(f"Resource not found: {endpoint}")
|
|
elif e.response.status_code == 429:
|
|
raise RateLimitError("Rate limit exceeded")
|
|
else:
|
|
raise APIError(f"API request failed: {e}")
|
|
except requests.exceptions.RequestException as e:
|
|
raise APIError(f"Network error: {e}")
|
|
|
|
class APIError(Exception): pass
|
|
class AuthenticationError(APIError): pass
|
|
class NotFoundError(APIError): pass
|
|
class RateLimitError(APIError): pass
|
|
```
|
|
|
|
### Workflow 3: Rate Limiting
|
|
|
|
```python
|
|
import time
|
|
from threading import Lock
|
|
|
|
class RateLimiter:
|
|
def __init__(self, calls_per_second):
|
|
self.calls_per_second = calls_per_second
|
|
self.min_interval = 1.0 / calls_per_second
|
|
self.last_call = 0
|
|
self.lock = Lock()
|
|
|
|
def __call__(self, func):
|
|
def wrapper(*args, **kwargs):
|
|
with self.lock:
|
|
elapsed = time.time() - self.last_call
|
|
if elapsed < self.min_interval:
|
|
time.sleep(self.min_interval - elapsed)
|
|
self.last_call = time.time()
|
|
return func(*args, **kwargs)
|
|
return wrapper
|
|
|
|
class RateLimitedClient:
|
|
def __init__(self, base_url, api_key, rate_limit=10):
|
|
self.client = APIClient(base_url, api_key)
|
|
self.limiter = RateLimiter(rate_limit)
|
|
|
|
@property
|
|
def get(self):
|
|
return self.limiter(self.client.get)
|
|
|
|
@property
|
|
def post(self):
|
|
return self.limiter(self.client.post)
|
|
```
|
|
|
|
### Workflow 4: Pagination Handling
|
|
|
|
```python
|
|
class PaginatedAPIClient(APIClient):
|
|
def get_all_pages(self, endpoint, params=None):
|
|
"""Fetch all pages of results"""
|
|
results = []
|
|
page = 1
|
|
params = params or {}
|
|
|
|
while True:
|
|
params['page'] = page
|
|
response = self.get(endpoint, params=params)
|
|
|
|
# Adjust based on API response structure
|
|
items = response.get('items', [])
|
|
results.extend(items)
|
|
|
|
# Check if more pages exist
|
|
if not response.get('has_more', False):
|
|
break
|
|
|
|
page += 1
|
|
|
|
return results
|
|
|
|
def get_all_cursor(self, endpoint, params=None):
|
|
"""Fetch all results using cursor-based pagination"""
|
|
results = []
|
|
cursor = None
|
|
params = params or {}
|
|
|
|
while True:
|
|
if cursor:
|
|
params['cursor'] = cursor
|
|
|
|
response = self.get(endpoint, params=params)
|
|
items = response.get('data', [])
|
|
results.extend(items)
|
|
|
|
cursor = response.get('next_cursor')
|
|
if not cursor:
|
|
break
|
|
|
|
return results
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Request Caching
|
|
```python
|
|
from functools import lru_cache
|
|
import hashlib
|
|
import json
|
|
|
|
class CachedAPIClient(APIClient):
|
|
def __init__(self, base_url, api_key, cache_ttl=300):
|
|
super().__init__(base_url, api_key)
|
|
self.cache = {}
|
|
self.cache_ttl = cache_ttl
|
|
|
|
def _cache_key(self, method, endpoint, params):
|
|
key_data = f"{method}:{endpoint}:{json.dumps(params, sort_keys=True)}"
|
|
return hashlib.md5(key_data.encode()).hexdigest()
|
|
|
|
def get_cached(self, endpoint, params=None):
|
|
cache_key = self._cache_key("GET", endpoint, params or {})
|
|
|
|
if cache_key in self.cache:
|
|
cached_data, cached_time = self.cache[cache_key]
|
|
if time.time() - cached_time < self.cache_ttl:
|
|
return cached_data
|
|
|
|
data = self.get(endpoint, params=params)
|
|
self.cache[cache_key] = (data, time.time())
|
|
return data
|
|
```
|
|
|
|
### Webhook Signature Verification
|
|
```python
|
|
import hmac
|
|
import hashlib
|
|
|
|
class WebhookValidator:
|
|
def __init__(self, secret):
|
|
self.secret = secret.encode()
|
|
|
|
def verify_signature(self, payload, signature_header):
|
|
"""Verify webhook signature"""
|
|
expected_signature = hmac.new(
|
|
self.secret,
|
|
payload.encode(),
|
|
hashlib.sha256
|
|
).hexdigest()
|
|
|
|
return hmac.compare_digest(expected_signature, signature_header)
|
|
```
|
|
|
|
## Testing API Integrations
|
|
|
|
### Using responses Library
|
|
```python
|
|
import responses
|
|
import requests
|
|
|
|
@responses.activate
|
|
def test_api_get():
|
|
# Mock the API response
|
|
responses.add(
|
|
responses.GET,
|
|
'https://api.example.com/users/123',
|
|
json={'id': 123, 'name': 'Alice'},
|
|
status=200
|
|
)
|
|
|
|
client = APIClient('https://api.example.com', 'test-key')
|
|
user = client.get('/users/123')
|
|
|
|
assert user['name'] == 'Alice'
|
|
|
|
@responses.activate
|
|
def test_api_error_handling():
|
|
responses.add(
|
|
responses.GET,
|
|
'https://api.example.com/users/999',
|
|
json={'error': 'Not found'},
|
|
status=404
|
|
)
|
|
|
|
client = RobustAPIClient('https://api.example.com', 'test-key')
|
|
|
|
with pytest.raises(NotFoundError):
|
|
client.request('GET', '/users/999')
|
|
```
|
|
|
|
## Common Pitfalls
|
|
|
|
### Issue: Leaking API Keys
|
|
**Solution:** Never hardcode keys. Use environment variables or secret management:
|
|
```python
|
|
import os
|
|
|
|
api_key = os.environ.get('API_KEY')
|
|
if not api_key:
|
|
raise ValueError("API_KEY environment variable not set")
|
|
```
|
|
|
|
### Issue: Not Handling Rate Limits
|
|
**Solution:** Implement exponential backoff and respect rate limit headers:
|
|
```python
|
|
def handle_rate_limit(response):
|
|
if response.status_code == 429:
|
|
retry_after = int(response.headers.get('Retry-After', 60))
|
|
time.sleep(retry_after)
|
|
# Retry request
|
|
```
|
|
|
|
### Issue: Timeout Issues
|
|
**Solution:** Always set timeouts:
|
|
```python
|
|
response = self.session.get(url, timeout=(3.0, 10.0)) # (connect, read)
|
|
```
|
|
```
|
|
|
|
---
|
|
|
|
## Example 3: Documentation Skill
|
|
|
|
### SKILL.md
|
|
```markdown
|
|
---
|
|
name: Technical Documentation Writer
|
|
description: Create clear, comprehensive technical documentation including API docs, README files, user guides, and code comments. Use when documenting code, APIs, or writing user-facing technical content.
|
|
---
|
|
|
|
## When to Use This Skill
|
|
|
|
Use this skill when:
|
|
- Writing README.md files for repositories
|
|
- Documenting APIs (REST, GraphQL, SDKs)
|
|
- Creating user guides and tutorials
|
|
- Writing inline code documentation
|
|
- Building developer onboarding materials
|
|
|
|
Do NOT use this skill for:
|
|
- Marketing copy or sales content
|
|
- Academic papers or research documentation
|
|
- Legal or compliance documentation
|
|
|
|
## Core Principles
|
|
|
|
1. **Write for your audience**: Junior developers need more context than senior engineers
|
|
2. **Show, don't just tell**: Include code examples for every concept
|
|
3. **Start with "why"**: Explain the purpose before the implementation
|
|
4. **Maintain consistency**: Use the same terminology throughout
|
|
5. **Keep it current**: Documentation that's out of date is worse than no documentation
|
|
|
|
## README.md Template
|
|
|
|
```markdown
|
|
# Project Name
|
|
|
|
Brief (1-2 sentence) description of what this project does.
|
|
|
|
## Features
|
|
|
|
- Key feature 1
|
|
- Key feature 2
|
|
- Key feature 3
|
|
|
|
## Installation
|
|
|
|
\```bash
|
|
npm install project-name
|
|
\```
|
|
|
|
## Quick Start
|
|
|
|
\```javascript
|
|
const Project = require('project-name');
|
|
|
|
const instance = new Project({
|
|
apiKey: 'your-api-key'
|
|
});
|
|
|
|
const result = await instance.doSomething();
|
|
console.log(result);
|
|
\```
|
|
|
|
## Documentation
|
|
|
|
Full documentation available at [link]
|
|
|
|
## Configuration
|
|
|
|
| Option | Type | Default | Description |
|
|
|--------|------|---------|-------------|
|
|
| apiKey | string | required | Your API key |
|
|
| timeout | number | 5000 | Request timeout in ms |
|
|
|
|
## Examples
|
|
|
|
### Example 1: Basic Usage
|
|
[Code example with explanation]
|
|
|
|
### Example 2: Advanced Pattern
|
|
[Code example with explanation]
|
|
|
|
## Contributing
|
|
|
|
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
|
|
## License
|
|
|
|
[License type] - see [LICENSE](LICENSE)
|
|
```
|
|
|
|
## API Documentation Template
|
|
|
|
```markdown
|
|
## endpoint_name
|
|
|
|
Brief description of what this endpoint does.
|
|
|
|
### HTTP Request
|
|
|
|
\```
|
|
POST /api/v1/resource
|
|
\```
|
|
|
|
### Parameters
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|-----------|------|----------|-------------|
|
|
| name | string | Yes | Resource name |
|
|
| type | string | No | Resource type (default: "standard") |
|
|
| metadata | object | No | Additional metadata |
|
|
|
|
### Request Example
|
|
|
|
\```json
|
|
{
|
|
"name": "example-resource",
|
|
"type": "premium",
|
|
"metadata": {
|
|
"created_by": "user123"
|
|
}
|
|
}
|
|
\```
|
|
|
|
### Response
|
|
|
|
\```json
|
|
{
|
|
"id": "res_abc123",
|
|
"name": "example-resource",
|
|
"type": "premium",
|
|
"status": "active",
|
|
"created_at": "2024-01-15T10:30:00Z"
|
|
}
|
|
\```
|
|
|
|
### Errors
|
|
|
|
| Status Code | Error Code | Description |
|
|
|-------------|------------|-------------|
|
|
| 400 | invalid_name | Name contains invalid characters |
|
|
| 401 | unauthorized | Invalid or missing API key |
|
|
| 409 | duplicate | Resource with this name already exists |
|
|
|
|
### Example Usage
|
|
|
|
\```python
|
|
import requests
|
|
|
|
response = requests.post(
|
|
'https://api.example.com/api/v1/resource',
|
|
headers={'Authorization': 'Bearer YOUR_API_KEY'},
|
|
json={
|
|
'name': 'example-resource',
|
|
'type': 'premium'
|
|
}
|
|
)
|
|
|
|
resource = response.json()
|
|
print(f"Created resource: {resource['id']}")
|
|
\```
|
|
```
|
|
|
|
## Code Comment Guidelines
|
|
|
|
### Function Documentation
|
|
|
|
**Python (docstring):**
|
|
```python
|
|
def calculate_discount(price: float, discount_percent: float, min_price: float = 0) -> float:
|
|
"""
|
|
Calculate discounted price with minimum price floor.
|
|
|
|
Args:
|
|
price: Original price before discount
|
|
discount_percent: Discount percentage (0-100)
|
|
min_price: Minimum price floor (default: 0)
|
|
|
|
Returns:
|
|
Final price after applying discount, never below min_price
|
|
|
|
Raises:
|
|
ValueError: If discount_percent is not between 0 and 100
|
|
ValueError: If price or min_price is negative
|
|
|
|
Examples:
|
|
>>> calculate_discount(100, 20)
|
|
80.0
|
|
>>> calculate_discount(100, 20, min_price=85)
|
|
85.0
|
|
"""
|
|
if not 0 <= discount_percent <= 100:
|
|
raise ValueError("Discount percent must be between 0 and 100")
|
|
if price < 0 or min_price < 0:
|
|
raise ValueError("Prices cannot be negative")
|
|
|
|
discounted = price * (1 - discount_percent / 100)
|
|
return max(discounted, min_price)
|
|
```
|
|
|
|
**JavaScript (JSDoc):**
|
|
```javascript
|
|
/**
|
|
* Fetch user data from the API with caching
|
|
*
|
|
* @param {string} userId - The unique user identifier
|
|
* @param {Object} options - Configuration options
|
|
* @param {boolean} [options.skipCache=false] - Whether to bypass cache
|
|
* @param {number} [options.timeout=5000] - Request timeout in ms
|
|
* @returns {Promise<User>} The user object
|
|
* @throws {NotFoundError} If user doesn't exist
|
|
* @throws {APIError} If the API request fails
|
|
*
|
|
* @example
|
|
* const user = await fetchUser('user123');
|
|
* console.log(user.name);
|
|
*
|
|
* @example
|
|
* // Skip cache for fresh data
|
|
* const user = await fetchUser('user123', { skipCache: true });
|
|
*/
|
|
async function fetchUser(userId, options = {}) {
|
|
// Implementation
|
|
}
|
|
```
|
|
|
|
### Inline Comments
|
|
|
|
**Good inline comments explain "why", not "what":**
|
|
|
|
```python
|
|
# Good: Explains reasoning
|
|
# Use a Set for O(1) lookup time since we'll be checking membership frequently
|
|
seen_ids = set()
|
|
|
|
# Bad: Just repeats what the code says
|
|
# Create a set called seen_ids
|
|
seen_ids = set()
|
|
```
|
|
|
|
```python
|
|
# Good: Explains non-obvious behavior
|
|
# Delay between requests to avoid hitting rate limit (10 req/sec)
|
|
time.sleep(0.1)
|
|
|
|
# Bad: States the obvious
|
|
# Sleep for 0.1 seconds
|
|
time.sleep(0.1)
|
|
```
|
|
|
|
## Common Pitfalls
|
|
|
|
### Issue: Documentation Out of Sync with Code
|
|
**Solution:**
|
|
- Keep docs close to code (docstrings, inline comments)
|
|
- Auto-generate API docs from code when possible
|
|
- Include doc updates in pull request checklist
|
|
- Set up CI checks for documentation completeness
|
|
|
|
### Issue: Too Much or Too Little Detail
|
|
**Solution:**
|
|
- README: High-level overview + quick start
|
|
- API Docs: Complete reference for every parameter
|
|
- Tutorials: Step-by-step with context
|
|
- Code Comments: Why, not what
|
|
|
|
### Issue: Examples Don't Run
|
|
**Solution:**
|
|
- Test all code examples as part of CI
|
|
- Use tools like doctest (Python) or jsdoc-to-markdown
|
|
- Include a "examples" directory with runnable code
|
|
- Version examples alongside code releases
|
|
```
|