[Avg. reading time: 15 minutes]
Code Quality & Safety
Type Hinting/Annotation
Type Hint
A type hint is a notation that suggests what type a variable, function parameter, or return value should be. It provides hints to developers and tools about the expected type but does not enforce them at runtime. Type hints can help catch type-related errors earlier through static analysis tools like mypy, and they enhance code readability and IDE support.
Type Annotation
Type annotation refers to the actual syntax used to provide these hints. It involves adding type information to variables, function parameters, and return types. Type annotations do not change how the code executes; they are purely for informational and tooling purposes.
Benefits
-
Improved Readability: Code with type annotations is easier to understand.
-
Tooling Support: IDEs can provide better autocompletion and error checking.
-
Static Analysis: Tools like mypy can check for type consistency, catching errors before runtime.
Basic Type Hints
age: int = 25
name: str = "Rachel"
is_active: bool = True
price: float = 19.99
Here, age is annotated as an int, and name is annotated as a str.
Collections
from typing import List, Set, Dict, Tuple
# List type hints
numbers: List[int] = [1, 2, 3]
names: List[str] = ["Alice", "Bob"]
# Set type hints
unique_ids: Set[int] = {1, 2, 3}
# Dictionary type hints
user_scores: Dict[str, int] = {"Alice": 95, "Bob": 87}
# Tuple type hints
point: Tuple[float, float] = (2.5, 3.0)
Function Annotations
def calculate_discount(price: float, discount_percent: float) -> float:
"""Calculate the final price after applying a discount."""
return price * (1 - discount_percent / 100)
def get_user_names(user_ids: List[int]) -> Dict[int, str]:
"""Return a mapping of user IDs to their names."""
return {uid: f"User {uid}" for uid in user_ids}
Advanced Type Hints
from typing import Optional, Union
def process_data(data: Optional[str] = None) -> str:
"""Process data with an optional input."""
if data is None:
return "No data provided"
return data.upper()
def format_value(value: Union[int, float, str]) -> str:
"""Format a value that could be integer, float, or string."""
return str(value)
Best Practices
- Consistency: Apply type hints consistently across your codebase.
- Documentation: Type hints complement but don’t replace docstrings.
- Type Checking: Use static type checkers like mypy.
# Run mypy on your code
mypy your_module.py
Secret Management
Proper secret management is crucial for application security. Secrets include API keys, database credentials, tokens, and other sensitive information that should never be hardcoded in your source code or committed to version control.
Either create them in Shell or .env
Shell
export SECRET_KEY='your_secret_value'
Windows Users
Goto Environment Variables via GUI and create one.
pip install python-dotenv
Create a empty file .env
.env
SECRET_KEY=your_secret_key
DATABASE_URL=your_database_url
main.py
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Access the environment variables
secret_key = os.getenv("SECRET_KEY")
database_url = os.getenv("DATABASE_URL")
print(f"Secret Key: {secret_key}")
print(f"Database URL: {database_url}")
Best Practices
Never commit secrets to version control
- Use .gitignore to exclude .env files
- Regularly audit git history for accidental commits
Sample .gitignore
# .gitignore
.env
.env.*
!.env.example
*.pem
*.key
secrets/
Create a .env.example file with dummy values:
# .env.example
SECRET_KEY=your_secret_key_here
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
API_KEY=your_api_key_here
DEBUG=False
Access Control
- Restrict environment variable access to necessary processes
- Use separate environment files for different environments (dev/staging/prod)
Secret Rotation
- Implement procedures for regular secret rotation
- Use separate secrets for different environments
Production Environments
Consider using cloud-native secret management services:
- AWS Secrets Manager
- Google Cloud Secret Manager
- Azure Key Vault
- HashiCorp Vault
PDOC
Python Documentation
pdoc is an automatic documentation generator for Python libraries. It builds on top of Python’s built-in doc attributes and type hints to create comprehensive API documentation. pdoc automatically extracts documentation from docstrings and generates HTML or Markdown output.
Docstring (Triple-quoted string)
def add(a: float, b: float) -> float:
"""
Add two numbers.
Args:
a (float): The first number to add.
b (float): The second number to add.
Returns:
float: The sum of the two numbers.
Example:
>>> add(2.5, 3.5)
6.0
"""
return a + b
def divide(a: float, b: float) -> float:
"""
Divide one number by another.
Args:
a (float): The dividend.
b (float): The divisor, must not be zero.
Returns:
float: The quotient of the division.
Raises:
ValueError: If the divisor (`b`) is zero.
Example:
>>> divide(10, 2)
5.0
"""
if b == 0:
raise ValueError("The divisor (b) must not be zero.")
return a / b
poetry add pdoc
or
pip install pdoc
poetry run pdoc filename.py -o ./docs
- pdoc.config.json allows customization
{
"docformat": "google",
"include": ["your_module"],
"exclude": ["tests", "docs"],
"template_dir": "custom_templates",
"output_dir": "api_docs"
}
````<span id='footer-class'>Ver 6.0.5</span>
<footer id="last-change">Last change: 2026-02-05</footer>````