Welcome to the Promptix project! We're excited to have you contribute. This document provides guidelines and best practices for contributing to the project.
- Development Setup
- Code Standards
- Documentation
- Testing
- Security
- Pull Request Process
- Release Process
- Python 3.9 or higher
- Git
- Make (optional, but recommended)
-
Clone the repository:
git clone https://github.com/Nisarg38/promptix-python.git cd promptix-python -
Set up development environment:
# Using Make (recommended) make setup-dev # Or manually: python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -e ".[dev]" pre-commit install
-
Verify setup:
make ci-check # Runs all quality checks
We provide a comprehensive Makefile for development tasks:
# Show all available commands
make help
# Quick development cycle
make dev-cycle # format, lint, type-check, test
# Full quality check
make quality # format, lint, type-check, test-coverage, security-audit, docs
# Run tests
make test # Basic tests
make test-coverage # With coverage report
make test-watch # Watch mode for TDD
# Code quality
make lint # All linting
make format # Auto-format code
make type-check # Type checking with mypy
make security-audit # Security scanning
# Documentation
make docs # Build documentation
make docs-serve # Serve docs locallyWe use strict code formatting and quality standards:
- Black for code formatting (88 character line length)
- isort for import sorting
- flake8 with plugins for linting
- mypy for type checking
- pydocstyle for docstring style (Google format)
All public functions, classes, and modules must have docstrings in Google format:
def example_function(param1: str, param2: Optional[int] = None) -> Dict[str, Any]:
"""
Brief description of the function.
Longer description if needed. Explain the purpose, behavior,
and any important details about the function.
Args:
param1: Description of the first parameter.
param2: Description of the second parameter. Defaults to None.
Returns:
Description of the return value and its structure.
Raises:
ValueError: When param1 is empty.
TypeError: When param2 is not an integer.
Example:
>>> result = example_function("test", 42)
>>> print(result)
{'status': 'success', 'data': 'test'}
"""
if not param1:
raise ValueError("param1 cannot be empty")
return {"status": "success", "data": param1}- All function signatures must include type hints
- Use
from typing importfor complex types - Prefer specific types over
Anywhen possible - Use
Optional[T]for optional parameters
from typing import Dict, List, Optional, Union
from pathlib import Path
def process_files(
file_paths: List[Path],
config: Optional[Dict[str, Any]] = None
) -> Union[str, None]:
"""Process multiple files with optional configuration."""
# Implementation here
pass- Use specific exception types, not generic
Exception - Provide meaningful error messages
- Log errors appropriately using the structured logging system
- Document all exceptions in docstrings
from promptix.core.exceptions import PromptNotFoundError
from promptix.enhancements.logging import get_logger
logger = get_logger(__name__)
def load_prompt(name: str) -> str:
"""
Load a prompt by name.
Args:
name: The name of the prompt to load.
Returns:
The prompt content.
Raises:
PromptNotFoundError: If the prompt doesn't exist.
ValueError: If name is empty or invalid.
"""
if not name or not name.strip():
raise ValueError("Prompt name cannot be empty")
try:
# Load prompt logic here
pass
except FileNotFoundError as e:
logger.error("Prompt file not found", extra={"prompt_name": name})
raise PromptNotFoundError(f"Prompt '{name}' not found") from e- Follow the existing project structure
- Group related functionality in modules
- Use dependency injection where appropriate
- Minimize circular dependencies
- Keep functions and classes focused (Single Responsibility Principle)
We use Sphinx for generating API documentation:
- All public APIs must be documented
- Include examples in docstrings
- Keep documentation up-to-date with code changes
- Update README.md for user-facing changes
- Add examples for new features
- Create guides for complex functionality
- All new features must include tests
- Aim for >80% test coverage
- Test both happy paths and error conditions
- Use meaningful test names that describe the scenario
import pytest
from promptix.core.exceptions import PromptNotFoundError
from promptix import Promptix
class TestPromptix:
"""Test suite for Promptix core functionality."""
def test_render_prompt_with_valid_template_returns_rendered_content(self):
"""Test that rendering a valid template returns the expected content."""
# Arrange
promptix = Promptix()
template_name = "greeting"
variables = {"name": "Alice"}
# Act
result = promptix.render_prompt(template_name, **variables)
# Assert
assert "Hello, Alice" in result
def test_render_prompt_with_missing_template_raises_prompt_not_found_error(self):
"""Test that rendering a non-existent template raises PromptNotFoundError."""
# Arrange
promptix = Promptix()
# Act & Assert
with pytest.raises(PromptNotFoundError, match="Template 'nonexistent' not found"):
promptix.render_prompt("nonexistent")Use pytest markers to categorize tests:
@pytest.mark.slow
def test_performance_with_large_dataset():
"""Test performance with a large dataset (marked as slow)."""
pass
@pytest.mark.integration
def test_api_integration():
"""Test integration with external APIs."""
passRun specific test categories:
# Skip slow tests
pytest -m "not slow"
# Run only integration tests
pytest -m integration- Never commit secrets, API keys, or sensitive data
- Use environment variables for configuration
- Validate all inputs
- Follow secure coding practices
- Regularly update dependencies
We use several tools for security scanning:
- bandit - Python security linter
- safety - Dependency vulnerability scanner
- pip-audit - Package vulnerability checker
Run security checks:
make security-auditIf you discover a security vulnerability, please:
- Do not create a public issue
- Email security@promptix.io with details
- Include steps to reproduce if possible
- Wait for acknowledgment before public disclosure
-
Run quality checks:
make quality
-
Update documentation if needed
-
Add tests for new functionality
-
Update CHANGELOG.md with your changes
-
Clear title and description:
- Use descriptive titles
- Explain what and why, not just how
- Reference related issues
-
Small, focused changes:
- One feature/fix per PR
- Break large changes into smaller PRs
- Keep PRs reviewable (< 500 lines when possible)
-
Code review process:
- Address all review comments
- Update tests if implementation changes
- Ensure CI passes
## Description
Brief description of changes and why they're needed.
## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
## Testing
- [ ] Tests pass locally
- [ ] Added tests for new functionality
- [ ] Updated documentation
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex logic
- [ ] Documentation updated
- [ ] CHANGELOG.md updatedWe follow Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features, backwards compatible
- PATCH: Bug fixes, backwards compatible
- Update version in
pyproject.toml - Update CHANGELOG.md with release notes
- Create release PR and get approval
- Tag release after merge
- GitHub Actions automatically publishes to PyPI
Include in CHANGELOG.md:
- Added: New features
- Changed: Changes in existing functionality
- Deprecated: Soon-to-be removed features
- Removed: Now removed features
- Fixed: Bug fixes
- Security: Security improvements
- Questions: Open a Discussion
- Bug Reports: Open an Issue
- Feature Requests: Open an Issue with the "enhancement" label
By contributing to Promptix, you agree that your contributions will be licensed under the MIT License.
Contributors are recognized in our Contributors page and in release notes for significant contributions.
Thank you for contributing to Promptix! 🚀