python LogoType Checking + Mypy

Python is a dynamically typed language, which means type checks typically happen at runtime. However, with the introduction of type hints (specified in PEP 484), Python developers can annotate their code with expected types for variables, function arguments, and return values. These type hints are not enforced by the Python interpreter during execution by default, but they provide crucial metadata for static analysis tools.

What is Type Checking?
Type checking is the process of verifying the type correctness of a program. In a dynamically typed language like Python, types are typically associated with values, not variables, and type errors might only manifest during runtime when an operation is performed on an incompatible type (e.g., trying to add a string to an integer).

Why use Type Hints?
1. Early Error Detection: Catch type-related bugs -before- running the code. This shifts bug discovery from runtime to development time, saving time and effort.
2. Improved Code Readability and Maintainability: Type hints act as explicit documentation, making it clear what type of data a function expects and returns, or what a variable holds. This significantly aids other developers (and your future self) in understanding and maintaining the codebase.
3. Enhanced IDE Support: Modern Integrated Development Environments (IDEs) and text editors (like VS Code, PyCharm) leverage type hints for better auto-completion, intelligent suggestions, refactoring tools, and immediate error highlighting.
4. Better Refactoring: With type information, refactoring tools can more safely rename or modify code, ensuring type compatibility is maintained.

What is Mypy?
Mypy is a popular and powerful static type checker for Python. It takes Python code with type hints and analyzes it -without executing it- to find inconsistencies and potential type errors. Mypy helps enforce the type contracts you've defined in your code.

How Mypy Works:
When you run `mypy` on your Python files, it performs a static analysis:
1. It reads your code and the type hints you've added.
2. It builds an understanding of the types flowing through your program.
3. It compares the actual usage of variables and function calls against the declared type hints.
4. If it finds any discrepancy (e.g., passing an `int` where a `str` is expected), it reports an error.

Benefits of using Mypy:
- Increased Robustness: Catches a wide class of bugs before they ever reach production.
- Code Quality Assurance: Acts as a quality gate, especially in Continuous Integration/Continuous Deployment (CI/CD) pipelines, ensuring that new code adheres to type safety.
- Confidence in Codebase: Developers can refactor and modify code with more confidence, knowing that `mypy` will flag any type-related regressions.
- Collaboration: Standardizes type expectations across a team, improving communication and reducing misunderstandings.

Basic Mypy Usage:
1. Installation: `pip install mypy`
2. Running: `mypy your_script.py` or `mypy your_package_directory`

Mypy allows gradual adoption of type hints. You don't have to type-hint your entire project at once; you can start with critical parts and expand as needed. It also supports various configuration options via `mypy.ini` or `pyproject.toml` for more granular control over its behavior.

Example Code

 First, ensure mypy is installed: pip install mypy

 --- my_typed_module.py ---
from typing import List, Dict, Union

def greet(name: str) -> str:
    """Greets a person by name."""
    return f"Hello, {name}!"

def add_numbers(a: int, b: int) -> int:
    """Adds two integers and returns their sum."""
    return a + b

def process_items(items: List[str]) -> None:
    """Prints each item in uppercase."""
    for item in items:
        print(item.upper())

def get_user_info(user_id: int) -> Union[Dict[str, str], None]:
    """Returns user info as a dictionary or None if not found."""
    if user_id == 1:
        return {"name": "Alice", "email": "alice@example.com"}
    return None

 --- Correct Usage (mypy should pass these) ---

 Variable annotations
username: str = "Bob"
welcome_message: str = greet(username)
print(welcome_message)

num1: int = 5
num2: int = 10
sum_result: int = add_numbers(num1, num2)
print(f"Sum: {sum_result}")

item_list: List[str] = ["apple", "banana", "cherry"]
process_items(item_list)

alice_info = get_user_info(1)
if alice_info:
    print(f"Alice's email: {alice_info['email']}")

 --- Incorrect Usage (mypy will flag these as errors) ---

 Incompatible type for argument 'name'
 invalid_name_message: str = greet(123)   Expects str, got int

 Incompatible type for arguments 'a' and 'b'
 invalid_sum_result: int = add_numbers("five", 10)   Expects int, got str

 Incompatible type for argument 'items'
 invalid_item_list: List[int] = [1, 2, 3]
 process_items(invalid_item_list)   Expects List[str], got List[int]

 Trying to access a dictionary key on a potentially None type
 user_data = get_user_info(2)  Returns None
 print(user_data['name'])  Mypy would warn about potential None access if configured


 --- How to run mypy ---
 1. Save the code above as `my_typed_module.py`
 2. Open your terminal or command prompt in the same directory.

 Run mypy on the file (with incorrect usage lines commented out):
 mypy my_typed_module.py
 Expected output: Success: no issues found in 1 source file

 Uncomment the lines marked as 'Incorrect Usage' (e.g., `invalid_name_message = greet(123)`) 
 and then run mypy again:
 mypy my_typed_module.py

 Expected output (mypy errors):
 my_typed_module.py:44: error: Argument "name" to "greet" has incompatible type "int"; expected "str"
 my_typed_module.py:47: error: Argument "a" to "add_numbers" has incompatible type "str"; expected "int"
 my_typed_module.py:51: error: Argument "items" to "process_items" has incompatible type "list[int]"; expected "list[str]"
 Found 3 errors in 1 file (checked 1 source file)