| description | Guidelines for writing high-quality, maintainable python code with best practices for logging, error handling, code organization, naming, formatting, and style. |
|---|---|
| applyTo | **/*.py |
This file is mastered in https://github.com/NHSDigital/eps-copilot-instructions and is automatically synced to all EPS repositories. To suggest changes, please open an issue or pull request in the eps-copilot-instructions repository.
These instructions are designed to guide GitHub Copilot in generating effective, maintainable, and domain-appropriate Python code. They are intended to be generic and applicable to a wide range of Python projects.
- Organize code into logical modules and packages. Use directories such as
core/,services/,utils/for separation of concerns. - Place entry points (e.g.,
handler.py) at the top level of the main package. - Use
__init__.pyfiles to define package boundaries and expose public APIs. - Group related functions and classes together. Avoid large monolithic files.
- Store tests in a dedicated
tests/directory, mirroring the structure of the main codebase.
- Use
snake_casefor function and variable names. - Use
PascalCasefor class names. - Prefix private functions and variables with a single underscore (
_). - Name modules and packages using short, descriptive, lowercase names.
- Use clear, descriptive names for all symbols. Avoid abbreviations unless they are widely understood.
- Follow PEP 8 for code style and formatting.
- Use 4 spaces per indentation level. Do not use tabs.
- Limit lines to 120 characters.
- Use blank lines to separate functions, classes, and logical sections.
- Place imports at the top of each file, grouped by standard library, third-party, and local imports.
- Use single quotes for strings unless double quotes are required.
- Add docstrings to all public modules, classes, and functions. Use triple double quotes for docstrings.
- Use the standard
logginglibrary for all logging. - Configure logging in the main entry point or via a dedicated utility module.
- Use appropriate log levels:
debug,info,warning,error,critical. - Avoid logging sensitive information.
- Include contextual information in log messages (e.g., function names, parameters, error details).
- Example:
import logging logger = logging.getLogger(__name__) logger.info('Processing event: %s', event)
- Use
try/exceptblocks to handle exceptions gracefully. - Catch specific exceptions rather than using bare
except. - Log exceptions with stack traces using
logger.exception(). - Raise custom exceptions for domain-specific errors.
- Validate inputs and fail fast with clear error messages.
- Example:
try: result = process_event(event) except ValueError as e: logger.error('Invalid event: %s', e) raise
- Write unit tests for all public functions and classes.
- Use
pytestas the preferred testing framework. - Name test files and functions using
test_prefix. - Use fixtures for setup and teardown.
- Mock external dependencies in tests.
- Ensure tests are isolated and repeatable.
- Use
pyproject.tomlto specify dependencies. - Never use
requirements.txtto specify dependencies. - Pin versions for critical dependencies.
- Avoid unnecessary dependencies.
- Document all public APIs with clear docstrings.
- Use Google or NumPy style for docstrings.
- Provide usage examples in README files.
- Do not log or expose secrets, credentials, or sensitive data.
- Validate and sanitize all external inputs.
- Use environment variables for configuration secrets.
- Prefer readability and simplicity over cleverness.
- Refactor duplicated code into reusable functions or classes.
- Use type hints for function signatures and variables where appropriate.
- Avoid global variables; use function arguments or class attributes.