Skip to content

Example Module

The Example module serves as the main entry point and orchestrator for the entire example framework. It provides a unified interface to the BaseExample classes, Calculator functionality, and utility functions.

Module Architecture

The example module is organized into several key components:

graph TB
    A[src.example] --> B[base.py]
    A --> C[calculator.py]
    A --> D[utils.py]

    B --> E[BaseExample]
    C --> F[Calculator]
    D --> G[Utility Functions]

    F -.-> E
    F -.-> G
    E -.-> G

Submodules Overview

Core Components

Submodule Purpose Key Exports
base Foundation classes and interfaces BaseExample, abstract patterns
calculator Mathematical operations Calculator class, arithmetic methods
utils Helper functions and utilities validate_input, format_number

Quick Start

Basic Usage

# Import the main components
from src.example import Calculator
from src.example.utils import validate_input, format_number

# Create calculator and perform operations
calc = Calculator()

# Validate inputs and perform calculation
a = validate_input("10.5")
b = validate_input("5.2")
result = calc.add(a, b)

# Format output
print(format_number(result))  # Output: 15.70

Advanced Integration

from src.example.base import BaseExample
from src.example.calculator import Calculator
from src.example.utils import process_list, merge_dicts

class AdvancedCalculator(BaseExample):
    """Advanced calculator extending base patterns."""

    def __init__(self, config=None):
        super().__init__(config)
        self.calc = Calculator()

    def batch_calculate(self, operations):
        """Process multiple calculations."""
        results = []
        for op, a, b in operations:
            result = getattr(self.calc, op)(a, b)
            results.append(result)
        return results

Package Configuration

The example module supports package-level configuration:

# Package configuration
EXAMPLE_CONFIG = {
    'default_calculator': Calculator,
    'strict_validation': True,
    'error_handling': 'graceful',
    'logging_enabled': True
}

Integration Patterns

With External Libraries

import numpy as np
from src.example import Calculator
from src.example.utils import format_number

# Integrate with NumPy
def numpy_calculator_bridge(np_array):
    """Bridge between NumPy and Calculator."""
    calc = Calculator()
    results = []

    for value in np_array:
        # Use calculator for individual operations
        result = calc.multiply(value, 2)
        results.append(result)

    return np.array(results)

With Configuration Management

from src.example.base import BaseExample
from src.example.utils import merge_dicts

class ConfigurableExample(BaseExample):
    """Example with external configuration support."""

    @classmethod
    def from_config_file(cls, config_path):
        """Create instance from configuration file."""
        with open(config_path) as f:
            config = json.load(f)

        # Merge with defaults
        default_config = cls.default_config()
        final_config = merge_dicts(default_config, config)

        return cls(config=final_config)

Error Handling Strategy

The example module implements a unified error handling strategy:

Exception Hierarchy

ExampleError
├── ValidationError      (from utils)
├── CalculationError     (from calculator)
├── BaseExampleError     (from base)
└── ConfigurationError   (from main module)

Centralized Error Handling

from src.example.exceptions import ExampleError

def safe_example_operation(operation, *args, **kwargs):
    """Safely execute any example operation."""
    try:
        return operation(*args, **kwargs)
    except ExampleError as e:
        logger.error(f"Example operation failed: {e}")
        return None
    except Exception as e:
        logger.critical(f"Unexpected error: {e}")
        raise

Testing Framework

The example module provides a comprehensive testing framework:

Test Utilities

from src.example.testing import ExampleTestCase

class TestMyExample(ExampleTestCase):
    """Test custom example implementations."""

    def setUp(self):
        """Set up test fixtures."""
        self.calc = self.create_calculator()
        self.test_data = self.load_test_data()

    def test_calculation_accuracy(self):
        """Test calculation accuracy."""
        result = self.calc.add(1.1, 2.2)
        self.assertAlmostEqual(result, 3.3, places=10)

Integration Testing

class TestExampleIntegration(ExampleTestCase):
    """Test integration between modules."""

    def test_full_pipeline(self):
        """Test complete processing pipeline."""
        # Test validation -> calculation -> formatting
        raw_input = "42.5"
        validated = validate_input(raw_input)
        result = self.calc.multiply(validated, 2)
        formatted = format_number(result)

        self.assertEqual(formatted, "85.00")

Performance Optimization

Caching Strategies

from functools import lru_cache
from src.example.calculator import Calculator

class OptimizedCalculator(Calculator):
    """Calculator with performance optimizations."""

    @lru_cache(maxsize=1000)
    def expensive_operation(self, a, b):
        """Cached expensive calculation."""
        return super().expensive_operation(a, b)

Batch Processing

from src.example.utils import process_list

def batch_validate_and_calculate(inputs, operation='add'):
    """Efficiently process multiple inputs."""
    # Batch validate inputs
    validated_inputs = process_list(inputs, validator=validate_input)

    # Batch process calculations
    calc = Calculator()
    results = []

    for i in range(0, len(validated_inputs), 2):
        a, b = validated_inputs[i:i+2]
        result = getattr(calc, operation)(a, b)
        results.append(result)

    return results

Documentation Generation

This module's documentation is automatically generated using mkdocstrings. Configuration details can be found in:

Migration and Upgrade

Version Compatibility

The example module maintains backward compatibility across versions:

# Handle version differences
import sys
from src.example import __version__

if __version__ >= "2.0.0":
    from src.example.calculator import AdvancedCalculator as Calculator
else:
    from src.example.calculator import Calculator

Best Practices

Module Usage

  1. Import Strategy: Import specific components rather than the entire module
  2. Configuration: Always provide explicit configuration for production use
  3. Error Handling: Use the unified error handling patterns
  4. Testing: Leverage the provided testing utilities
  5. Performance: Use batch operations for multiple items

Code Organization

# Recommended import pattern
from src.example.base import BaseExample
from src.example.calculator import Calculator
from src.example.utils import validate_input, format_number

# Avoid importing the entire module
# from src.example import *  # Not recommended

Examples and Tutorials

For comprehensive examples and tutorials:

API Reference

Example module for demonstrating mkdocstrings.

This module contains example classes and functions to showcase API documentation generation capabilities.

Classes

AbstractBase

AbstractBase(initial_value: Optional[T] = None)

Bases: ABC, Generic[T]

Abstract base class for creating custom implementations.

This abstract class defines the interface that all concrete implementations must follow. It uses generics to allow flexible type handling.

Type Parameters
See Also
  • :class:BaseClass: Non-abstract base implementation
  • :mod:typing: Type hints documentation

Initialize the abstract base.

Parameters:

Name Type Description Default
initial_value Optional[T]

Optional initial value to store

None
Source code in src/example/base.py
def __init__(self, initial_value: Optional[T] = None) -> None:
    """Initialize the abstract base.

    Args:
        initial_value: Optional initial value to store
    """
    self._value: Optional[T] = initial_value

Attributes

value property writable
value: Optional[T]

Get the current stored value.

Returns:

Type Description
Optional[T]

The stored value or None

Functions

process abstractmethod
process(data: T) -> T

Process the input data.

This method must be implemented by subclasses.

Parameters:

Name Type Description Default
data T

Input data to process

required

Returns:

Type Description
T

Processed data of the same type

Raises:

Type Description
NotImplementedError

If called on abstract class

Source code in src/example/base.py
@abstractmethod
def process(self, data: T) -> T:
    """Process the input data.

    This method must be implemented by subclasses.

    Args:
        data: Input data to process

    Returns:
        Processed data of the same type

    Raises:
        NotImplementedError: If called on abstract class
    """
    raise NotImplementedError("Subclasses must implement process()")
validate abstractmethod
validate(data: T) -> bool

Validate the input data.

Parameters:

Name Type Description Default
data T

Data to validate

required

Returns:

Type Description
bool

True if data is valid, False otherwise

Source code in src/example/base.py
@abstractmethod
def validate(self, data: T) -> bool:
    """Validate the input data.

    Args:
        data: Data to validate

    Returns:
        True if data is valid, False otherwise
    """
    pass
reset
reset() -> None

Reset the stored value to None.

Source code in src/example/base.py
def reset(self) -> None:
    """Reset the stored value to None."""
    self._value = None

BaseClass

BaseClass(name: str)

A base class demonstrating basic documentation.

This class shows how to document a simple Python class with attributes, methods, and properties.

Attributes:

Name Type Description
name

The name of the instance

created_at

Timestamp of instance creation

_internal_id

Internal identifier (private)

Example
# Create an instance
obj = BaseClass("example")

# Access properties
print(obj.name)  # "example"
print(obj.age_seconds)  # Time since creation

Initialize a new BaseClass instance.

Parameters:

Name Type Description Default
name str

The name to assign to this instance

required

Raises:

Type Description
ValueError

If name is empty or None

Source code in src/example/base.py
def __init__(self, name: str) -> None:
    """Initialize a new BaseClass instance.

    Args:
        name: The name to assign to this instance

    Raises:
        ValueError: If name is empty or None
    """
    if not name:
        raise ValueError("Name cannot be empty")

    self.name = name
    self.created_at = datetime.now()
    self._internal_id = id(self)

Attributes

age_seconds property
age_seconds: float

Calculate age of instance in seconds.

Returns:

Type Description
float

Number of seconds since instance creation

Functions

update_name
update_name(new_name: str) -> None

Update the instance name.

Parameters:

Name Type Description Default
new_name str

The new name to set

required

Raises:

Type Description
ValueError

If new_name is empty

Note

This method validates the input before updating.

Source code in src/example/base.py
def update_name(self, new_name: str) -> None:
    """Update the instance name.

    Args:
        new_name: The new name to set

    Raises:
        ValueError: If new_name is empty

    Note:
        This method validates the input before updating.
    """
    if not new_name:
        raise ValueError("New name cannot be empty")
    self.name = new_name

Calculator

Calculator(precision: int = 4)

Advanced calculator with history tracking.

This calculator supports basic arithmetic operations and maintains a history of all calculations performed.

Attributes:

Name Type Description
history List[str]

List of calculation history entries

precision

Number of decimal places for results

Example
# Create calculator instance
calc = Calculator(precision=2)

# Perform calculations
result = calc.add(10, 5)  # 15.0
result = calc.multiply(3, 4)  # 12.0

# Check history
for entry in calc.history:
    print(entry)
Note

The calculator automatically rounds results based on the specified precision.

Initialize calculator with specified precision.

Parameters:

Name Type Description Default
precision int

Number of decimal places for results (default: 4)

4

Raises:

Type Description
ValueError

If precision is negative

Source code in src/example/calculator.py
def __init__(self, precision: int = 4) -> None:
    """Initialize calculator with specified precision.

    Args:
        precision: Number of decimal places for results (default: 4)

    Raises:
        ValueError: If precision is negative
    """
    if precision < 0:
        raise ValueError("Precision must be non-negative")

    self.history: List[str] = []
    self.precision = precision

Functions

add
add(a: Union[int, float], b: Union[int, float]) -> float

Add two numbers.

Parameters:

Name Type Description Default
a Union[int, float]

First number

required
b Union[int, float]

Second number

required

Returns:

Type Description
float

Sum of a and b

Example

calc = Calculator() calc.add(5, 3) 8.0

Source code in src/example/calculator.py
def add(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Add two numbers.

    Args:
        a: First number
        b: Second number

    Returns:
        Sum of a and b

    Example:
        >>> calc = Calculator()
        >>> calc.add(5, 3)
        8.0
    """
    result = round(a + b, self.precision)
    self._record_operation(MathOperations.ADD, (a, b), result)
    return result
subtract
subtract(a: Union[int, float], b: Union[int, float]) -> float

Subtract b from a.

Parameters:

Name Type Description Default
a Union[int, float]

Number to subtract from

required
b Union[int, float]

Number to subtract

required

Returns:

Type Description
float

Difference of a and b

Example

calc = Calculator() calc.subtract(10, 4) 6.0

Source code in src/example/calculator.py
def subtract(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Subtract b from a.

    Args:
        a: Number to subtract from
        b: Number to subtract

    Returns:
        Difference of a and b

    Example:
        >>> calc = Calculator()
        >>> calc.subtract(10, 4)
        6.0
    """
    result = round(a - b, self.precision)
    self._record_operation(MathOperations.SUBTRACT, (a, b), result)
    return result
multiply
multiply(a: Union[int, float], b: Union[int, float]) -> float

Multiply two numbers.

Parameters:

Name Type Description Default
a Union[int, float]

First factor

required
b Union[int, float]

Second factor

required

Returns:

Type Description
float

Product of a and b

Example

calc = Calculator() calc.multiply(3, 7) 21.0

Source code in src/example/calculator.py
def multiply(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Multiply two numbers.

    Args:
        a: First factor
        b: Second factor

    Returns:
        Product of a and b

    Example:
        >>> calc = Calculator()
        >>> calc.multiply(3, 7)
        21.0
    """
    result = round(a * b, self.precision)
    self._record_operation(MathOperations.MULTIPLY, (a, b), result)
    return result
divide
divide(a: Union[int, float], b: Union[int, float]) -> float

Divide a by b.

Parameters:

Name Type Description Default
a Union[int, float]

Dividend

required
b Union[int, float]

Divisor

required

Returns:

Type Description
float

Quotient of a divided by b

Raises:

Type Description
ZeroDivisionError

If b is zero

Example

calc = Calculator() calc.divide(15, 3) 5.0

Source code in src/example/calculator.py
def divide(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Divide a by b.

    Args:
        a: Dividend
        b: Divisor

    Returns:
        Quotient of a divided by b

    Raises:
        ZeroDivisionError: If b is zero

    Example:
        >>> calc = Calculator()
        >>> calc.divide(15, 3)
        5.0
    """
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero")

    result = round(a / b, self.precision)
    self._record_operation(MathOperations.DIVIDE, (a, b), result)
    return result
power
power(base: int, exponent: int) -> int
power(base: float, exponent: float) -> float
power(base: Union[int, float], exponent: Union[int, float]) -> Union[int, float]

Raise base to the power of exponent.

Parameters:

Name Type Description Default
base Union[int, float]

The base number

required
exponent Union[int, float]

The exponent

required

Returns:

Type Description
Union[int, float]

base raised to the power of exponent

Example

calc = Calculator() calc.power(2, 3) 8 calc.power(2.5, 2) 6.25

Source code in src/example/calculator.py
def power(
    self, base: Union[int, float], exponent: Union[int, float]
) -> Union[int, float]:
    """Raise base to the power of exponent.

    Args:
        base: The base number
        exponent: The exponent

    Returns:
        base raised to the power of exponent

    Example:
        >>> calc = Calculator()
        >>> calc.power(2, 3)
        8
        >>> calc.power(2.5, 2)
        6.25
    """
    result = base**exponent
    if isinstance(base, int) and isinstance(exponent, int) and exponent >= 0:
        self._record_operation(MathOperations.POWER, (base, exponent), result)
        return int(result)
    else:
        result = round(result, self.precision)
        self._record_operation(MathOperations.POWER, (base, exponent), result)
        return result
sqrt
sqrt(number: Union[int, float]) -> float

Calculate square root.

Parameters:

Name Type Description Default
number Union[int, float]

Number to find square root of

required

Returns:

Type Description
float

Square root of the number

Raises:

Type Description
ValueError

If number is negative

Example

calc = Calculator() calc.sqrt(16) 4.0

Source code in src/example/calculator.py
def sqrt(self, number: Union[int, float]) -> float:
    """Calculate square root.

    Args:
        number: Number to find square root of

    Returns:
        Square root of the number

    Raises:
        ValueError: If number is negative

    Example:
        >>> calc = Calculator()
        >>> calc.sqrt(16)
        4.0
    """
    if number < 0:
        raise ValueError("Cannot calculate square root of negative number")

    result = round(math.sqrt(number), self.precision)
    self._record_operation(MathOperations.ROOT, (number,), result)
    return result
clear_history
clear_history() -> None

Clear the calculation history.

Source code in src/example/calculator.py
def clear_history(self) -> None:
    """Clear the calculation history."""
    self.history.clear()
get_statistics
get_statistics() -> dict

Get statistics about calculator usage.

Returns:

Type Description
dict

Dictionary containing usage statistics including:

dict
  • total_operations: Total number of operations performed
dict
  • operation_counts: Count of each operation type
Example

calc = Calculator() calc.add(1, 2) 3.0 calc.multiply(3, 4) 12.0 stats = calc.get_statistics() stats['total_operations'] 2

Source code in src/example/calculator.py
def get_statistics(self) -> dict:
    """Get statistics about calculator usage.

    Returns:
        Dictionary containing usage statistics including:
        - total_operations: Total number of operations performed
        - operation_counts: Count of each operation type

    Example:
        >>> calc = Calculator()
        >>> calc.add(1, 2)
        3.0
        >>> calc.multiply(3, 4)
        12.0
        >>> stats = calc.get_statistics()
        >>> stats['total_operations']
        2
    """
    stats = {
        "total_operations": len(self.history),
        "operation_counts": {op.name: 0 for op in MathOperations},
    }

    for entry in self.history:
        for op in MathOperations:
            if op.value in entry:
                stats["operation_counts"][op.name] += 1
                break

    return stats

MathOperations

Bases: Enum

Enumeration of supported mathematical operations.

This enum defines all operations supported by the Calculator class.

Attributes:

Name Type Description
ADD

Addition operation

SUBTRACT

Subtraction operation

MULTIPLY

Multiplication operation

DIVIDE

Division operation

POWER

Exponentiation operation

ROOT

Root operation (square root by default)

Functions

format_number

format_number(number: Union[int, float], decimals: int = 2, thousands_separator: bool = True) -> str

Format a number for display.

Parameters:

Name Type Description Default
number Union[int, float]

The number to format

required
decimals int

Number of decimal places (default: 2)

2
thousands_separator bool

Whether to use thousands separator (default: True)

True

Returns:

Type Description
str

Formatted number as string

Example

format_number(1234567.89) '1,234,567.89' format_number(1234567.89, decimals=0) '1,234,568' format_number(1234.5, thousands_separator=False) '1234.50'

See Also
  • :func:validate_input: Validate numeric input
  • locale.format_string: For locale-specific formatting
Source code in src/example/utils.py
def format_number(
    number: Union[int, float], decimals: int = 2, thousands_separator: bool = True
) -> str:
    """Format a number for display.

    Args:
        number: The number to format
        decimals: Number of decimal places (default: 2)
        thousands_separator: Whether to use thousands separator (default: True)

    Returns:
        Formatted number as string

    Example:
        >>> format_number(1234567.89)
        '1,234,567.89'
        >>> format_number(1234567.89, decimals=0)
        '1,234,568'
        >>> format_number(1234.5, thousands_separator=False)
        '1234.50'

    See Also:
        - :func:`validate_input`: Validate numeric input
        - `locale.format_string`: For locale-specific formatting
    """
    if thousands_separator:
        return f"{number:,.{decimals}f}"
    else:
        return f"{number:.{decimals}f}"

timer

timer(func: F) -> F

Decorator to measure function execution time.

This decorator wraps a function and prints the time taken to execute it.

Parameters:

Name Type Description Default
func F

The function to time

required

Returns:

Type Description
F

Wrapped function that prints execution time

Example
@timer
def slow_function():
    time.sleep(1)
    return "Done"

result = slow_function()
# Output: slow_function took 1.0012 seconds
Note

The timing includes all operations within the function, including any I/O operations.

Source code in src/example/utils.py
def timer(func: F) -> F:
    """Decorator to measure function execution time.

    This decorator wraps a function and prints the time taken
    to execute it.

    Args:
        func: The function to time

    Returns:
        Wrapped function that prints execution time

    Example:
        ```python
        @timer
        def slow_function():
            time.sleep(1)
            return "Done"

        result = slow_function()
        # Output: slow_function took 1.0012 seconds
        ```

    Note:
        The timing includes all operations within the function,
        including any I/O operations.
    """

    @functools.wraps(func)
    def wrapper(*args: Any, **kwargs: Any) -> Any:
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f} seconds")
        return result

    return wrapper  # type: ignore

validate_input

validate_input(value: Any, expected_type: type, min_value: Optional[Union[int, float]] = None, max_value: Optional[Union[int, float]] = None, allow_none: bool = False) -> bool

Validate input value against constraints.

This function checks if a value meets specified type and range constraints.

Parameters:

Name Type Description Default
value Any

The value to validate

required
expected_type type

Expected type of the value

required
min_value Optional[Union[int, float]]

Minimum allowed value (for numeric types)

None
max_value Optional[Union[int, float]]

Maximum allowed value (for numeric types)

None
allow_none bool

Whether None is a valid value

False

Returns:

Type Description
bool

True if value is valid, False otherwise

Example

validate_input(42, int, min_value=0, max_value=100) True validate_input(-5, int, min_value=0) False validate_input(None, str, allow_none=True) True

Warning

This function only performs basic validation. For complex validation logic, consider using a dedicated validation library like pydantic or cerberus.

Source code in src/example/utils.py
def validate_input(
    value: Any,
    expected_type: type,
    min_value: Optional[Union[int, float]] = None,
    max_value: Optional[Union[int, float]] = None,
    allow_none: bool = False,
) -> bool:
    """Validate input value against constraints.

    This function checks if a value meets specified type and range
    constraints.

    Args:
        value: The value to validate
        expected_type: Expected type of the value
        min_value: Minimum allowed value (for numeric types)
        max_value: Maximum allowed value (for numeric types)
        allow_none: Whether None is a valid value

    Returns:
        True if value is valid, False otherwise

    Example:
        >>> validate_input(42, int, min_value=0, max_value=100)
        True
        >>> validate_input(-5, int, min_value=0)
        False
        >>> validate_input(None, str, allow_none=True)
        True

    Warning:
        This function only performs basic validation. For complex
        validation logic, consider using a dedicated validation library
        like `pydantic` or `cerberus`.
    """
    if value is None:
        return allow_none

    if not isinstance(value, expected_type):
        return False

    if expected_type in (int, float):
        if min_value is not None and value < min_value:
            return False
        if max_value is not None and value > max_value:
            return False

    return True

Modules

base

Base classes and abstract interfaces.

This module provides base classes that can be extended for creating custom implementations.

Classes

BaseClass
BaseClass(name: str)

A base class demonstrating basic documentation.

This class shows how to document a simple Python class with attributes, methods, and properties.

Attributes:

Name Type Description
name

The name of the instance

created_at

Timestamp of instance creation

_internal_id

Internal identifier (private)

Example
# Create an instance
obj = BaseClass("example")

# Access properties
print(obj.name)  # "example"
print(obj.age_seconds)  # Time since creation

Initialize a new BaseClass instance.

Parameters:

Name Type Description Default
name str

The name to assign to this instance

required

Raises:

Type Description
ValueError

If name is empty or None

Source code in src/example/base.py
def __init__(self, name: str) -> None:
    """Initialize a new BaseClass instance.

    Args:
        name: The name to assign to this instance

    Raises:
        ValueError: If name is empty or None
    """
    if not name:
        raise ValueError("Name cannot be empty")

    self.name = name
    self.created_at = datetime.now()
    self._internal_id = id(self)
Attributes
age_seconds property
age_seconds: float

Calculate age of instance in seconds.

Returns:

Type Description
float

Number of seconds since instance creation

Functions
update_name
update_name(new_name: str) -> None

Update the instance name.

Parameters:

Name Type Description Default
new_name str

The new name to set

required

Raises:

Type Description
ValueError

If new_name is empty

Note

This method validates the input before updating.

Source code in src/example/base.py
def update_name(self, new_name: str) -> None:
    """Update the instance name.

    Args:
        new_name: The new name to set

    Raises:
        ValueError: If new_name is empty

    Note:
        This method validates the input before updating.
    """
    if not new_name:
        raise ValueError("New name cannot be empty")
    self.name = new_name
AbstractBase
AbstractBase(initial_value: Optional[T] = None)

Bases: ABC, Generic[T]

Abstract base class for creating custom implementations.

This abstract class defines the interface that all concrete implementations must follow. It uses generics to allow flexible type handling.

Type Parameters
See Also
  • :class:BaseClass: Non-abstract base implementation
  • :mod:typing: Type hints documentation

Initialize the abstract base.

Parameters:

Name Type Description Default
initial_value Optional[T]

Optional initial value to store

None
Source code in src/example/base.py
def __init__(self, initial_value: Optional[T] = None) -> None:
    """Initialize the abstract base.

    Args:
        initial_value: Optional initial value to store
    """
    self._value: Optional[T] = initial_value
Attributes
value property writable
value: Optional[T]

Get the current stored value.

Returns:

Type Description
Optional[T]

The stored value or None

Functions
process abstractmethod
process(data: T) -> T

Process the input data.

This method must be implemented by subclasses.

Parameters:

Name Type Description Default
data T

Input data to process

required

Returns:

Type Description
T

Processed data of the same type

Raises:

Type Description
NotImplementedError

If called on abstract class

Source code in src/example/base.py
@abstractmethod
def process(self, data: T) -> T:
    """Process the input data.

    This method must be implemented by subclasses.

    Args:
        data: Input data to process

    Returns:
        Processed data of the same type

    Raises:
        NotImplementedError: If called on abstract class
    """
    raise NotImplementedError("Subclasses must implement process()")
validate abstractmethod
validate(data: T) -> bool

Validate the input data.

Parameters:

Name Type Description Default
data T

Data to validate

required

Returns:

Type Description
bool

True if data is valid, False otherwise

Source code in src/example/base.py
@abstractmethod
def validate(self, data: T) -> bool:
    """Validate the input data.

    Args:
        data: Data to validate

    Returns:
        True if data is valid, False otherwise
    """
    pass
reset
reset() -> None

Reset the stored value to None.

Source code in src/example/base.py
def reset(self) -> None:
    """Reset the stored value to None."""
    self._value = None

calculator

Calculator module with mathematical operations.

This module provides calculator functionality with support for basic arithmetic operations and advanced mathematical functions.

Classes

MathOperations

Bases: Enum

Enumeration of supported mathematical operations.

This enum defines all operations supported by the Calculator class.

Attributes:

Name Type Description
ADD

Addition operation

SUBTRACT

Subtraction operation

MULTIPLY

Multiplication operation

DIVIDE

Division operation

POWER

Exponentiation operation

ROOT

Root operation (square root by default)

Calculator
Calculator(precision: int = 4)

Advanced calculator with history tracking.

This calculator supports basic arithmetic operations and maintains a history of all calculations performed.

Attributes:

Name Type Description
history List[str]

List of calculation history entries

precision

Number of decimal places for results

Example
# Create calculator instance
calc = Calculator(precision=2)

# Perform calculations
result = calc.add(10, 5)  # 15.0
result = calc.multiply(3, 4)  # 12.0

# Check history
for entry in calc.history:
    print(entry)
Note

The calculator automatically rounds results based on the specified precision.

Initialize calculator with specified precision.

Parameters:

Name Type Description Default
precision int

Number of decimal places for results (default: 4)

4

Raises:

Type Description
ValueError

If precision is negative

Source code in src/example/calculator.py
def __init__(self, precision: int = 4) -> None:
    """Initialize calculator with specified precision.

    Args:
        precision: Number of decimal places for results (default: 4)

    Raises:
        ValueError: If precision is negative
    """
    if precision < 0:
        raise ValueError("Precision must be non-negative")

    self.history: List[str] = []
    self.precision = precision
Functions
add
add(a: Union[int, float], b: Union[int, float]) -> float

Add two numbers.

Parameters:

Name Type Description Default
a Union[int, float]

First number

required
b Union[int, float]

Second number

required

Returns:

Type Description
float

Sum of a and b

Example

calc = Calculator() calc.add(5, 3) 8.0

Source code in src/example/calculator.py
def add(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Add two numbers.

    Args:
        a: First number
        b: Second number

    Returns:
        Sum of a and b

    Example:
        >>> calc = Calculator()
        >>> calc.add(5, 3)
        8.0
    """
    result = round(a + b, self.precision)
    self._record_operation(MathOperations.ADD, (a, b), result)
    return result
subtract
subtract(a: Union[int, float], b: Union[int, float]) -> float

Subtract b from a.

Parameters:

Name Type Description Default
a Union[int, float]

Number to subtract from

required
b Union[int, float]

Number to subtract

required

Returns:

Type Description
float

Difference of a and b

Example

calc = Calculator() calc.subtract(10, 4) 6.0

Source code in src/example/calculator.py
def subtract(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Subtract b from a.

    Args:
        a: Number to subtract from
        b: Number to subtract

    Returns:
        Difference of a and b

    Example:
        >>> calc = Calculator()
        >>> calc.subtract(10, 4)
        6.0
    """
    result = round(a - b, self.precision)
    self._record_operation(MathOperations.SUBTRACT, (a, b), result)
    return result
multiply
multiply(a: Union[int, float], b: Union[int, float]) -> float

Multiply two numbers.

Parameters:

Name Type Description Default
a Union[int, float]

First factor

required
b Union[int, float]

Second factor

required

Returns:

Type Description
float

Product of a and b

Example

calc = Calculator() calc.multiply(3, 7) 21.0

Source code in src/example/calculator.py
def multiply(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Multiply two numbers.

    Args:
        a: First factor
        b: Second factor

    Returns:
        Product of a and b

    Example:
        >>> calc = Calculator()
        >>> calc.multiply(3, 7)
        21.0
    """
    result = round(a * b, self.precision)
    self._record_operation(MathOperations.MULTIPLY, (a, b), result)
    return result
divide
divide(a: Union[int, float], b: Union[int, float]) -> float

Divide a by b.

Parameters:

Name Type Description Default
a Union[int, float]

Dividend

required
b Union[int, float]

Divisor

required

Returns:

Type Description
float

Quotient of a divided by b

Raises:

Type Description
ZeroDivisionError

If b is zero

Example

calc = Calculator() calc.divide(15, 3) 5.0

Source code in src/example/calculator.py
def divide(self, a: Union[int, float], b: Union[int, float]) -> float:
    """Divide a by b.

    Args:
        a: Dividend
        b: Divisor

    Returns:
        Quotient of a divided by b

    Raises:
        ZeroDivisionError: If b is zero

    Example:
        >>> calc = Calculator()
        >>> calc.divide(15, 3)
        5.0
    """
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero")

    result = round(a / b, self.precision)
    self._record_operation(MathOperations.DIVIDE, (a, b), result)
    return result
power
power(base: int, exponent: int) -> int
power(base: float, exponent: float) -> float
power(base: Union[int, float], exponent: Union[int, float]) -> Union[int, float]

Raise base to the power of exponent.

Parameters:

Name Type Description Default
base Union[int, float]

The base number

required
exponent Union[int, float]

The exponent

required

Returns:

Type Description
Union[int, float]

base raised to the power of exponent

Example

calc = Calculator() calc.power(2, 3) 8 calc.power(2.5, 2) 6.25

Source code in src/example/calculator.py
def power(
    self, base: Union[int, float], exponent: Union[int, float]
) -> Union[int, float]:
    """Raise base to the power of exponent.

    Args:
        base: The base number
        exponent: The exponent

    Returns:
        base raised to the power of exponent

    Example:
        >>> calc = Calculator()
        >>> calc.power(2, 3)
        8
        >>> calc.power(2.5, 2)
        6.25
    """
    result = base**exponent
    if isinstance(base, int) and isinstance(exponent, int) and exponent >= 0:
        self._record_operation(MathOperations.POWER, (base, exponent), result)
        return int(result)
    else:
        result = round(result, self.precision)
        self._record_operation(MathOperations.POWER, (base, exponent), result)
        return result
sqrt
sqrt(number: Union[int, float]) -> float

Calculate square root.

Parameters:

Name Type Description Default
number Union[int, float]

Number to find square root of

required

Returns:

Type Description
float

Square root of the number

Raises:

Type Description
ValueError

If number is negative

Example

calc = Calculator() calc.sqrt(16) 4.0

Source code in src/example/calculator.py
def sqrt(self, number: Union[int, float]) -> float:
    """Calculate square root.

    Args:
        number: Number to find square root of

    Returns:
        Square root of the number

    Raises:
        ValueError: If number is negative

    Example:
        >>> calc = Calculator()
        >>> calc.sqrt(16)
        4.0
    """
    if number < 0:
        raise ValueError("Cannot calculate square root of negative number")

    result = round(math.sqrt(number), self.precision)
    self._record_operation(MathOperations.ROOT, (number,), result)
    return result
clear_history
clear_history() -> None

Clear the calculation history.

Source code in src/example/calculator.py
def clear_history(self) -> None:
    """Clear the calculation history."""
    self.history.clear()
get_statistics
get_statistics() -> dict

Get statistics about calculator usage.

Returns:

Type Description
dict

Dictionary containing usage statistics including:

dict
  • total_operations: Total number of operations performed
dict
  • operation_counts: Count of each operation type
Example

calc = Calculator() calc.add(1, 2) 3.0 calc.multiply(3, 4) 12.0 stats = calc.get_statistics() stats['total_operations'] 2

Source code in src/example/calculator.py
def get_statistics(self) -> dict:
    """Get statistics about calculator usage.

    Returns:
        Dictionary containing usage statistics including:
        - total_operations: Total number of operations performed
        - operation_counts: Count of each operation type

    Example:
        >>> calc = Calculator()
        >>> calc.add(1, 2)
        3.0
        >>> calc.multiply(3, 4)
        12.0
        >>> stats = calc.get_statistics()
        >>> stats['total_operations']
        2
    """
    stats = {
        "total_operations": len(self.history),
        "operation_counts": {op.name: 0 for op in MathOperations},
    }

    for entry in self.history:
        for op in MathOperations:
            if op.value in entry:
                stats["operation_counts"][op.name] += 1
                break

    return stats

utils

Utility functions for the example package.

This module contains helper functions and decorators that can be used throughout the application.

Classes

DateFormatter
DateFormatter(default_format: str = '%Y-%m-%d %H:%M:%S')

Format dates in various formats.

This class provides methods to format datetime objects into different string representations.

Attributes:

Name Type Description
default_format

Default format string for dates

Example
formatter = DateFormatter()
now = datetime.now()

# Use default format
print(formatter.format(now))

# Use custom format
print(formatter.format(now, "%B %d, %Y"))

# Get relative time
print(formatter.relative_time(now))

Initialize formatter with default format.

Parameters:

Name Type Description Default
default_format str

Default strftime format string

'%Y-%m-%d %H:%M:%S'
Source code in src/example/utils.py
def __init__(self, default_format: str = "%Y-%m-%d %H:%M:%S") -> None:
    """Initialize formatter with default format.

    Args:
        default_format: Default strftime format string
    """
    self.default_format = default_format
Functions
format
format(date: datetime, format_string: Optional[str] = None) -> str

Format a datetime object.

Parameters:

Name Type Description Default
date datetime

The datetime to format

required
format_string Optional[str]

Optional format string (uses default if None)

None

Returns:

Type Description
str

Formatted date string

Example

formatter = DateFormatter() date = datetime(2024, 1, 15, 14, 30, 45) formatter.format(date) '2024-01-15 14:30:45'

Source code in src/example/utils.py
def format(self, date: datetime, format_string: Optional[str] = None) -> str:
    """Format a datetime object.

    Args:
        date: The datetime to format
        format_string: Optional format string (uses default if None)

    Returns:
        Formatted date string

    Example:
        >>> formatter = DateFormatter()
        >>> date = datetime(2024, 1, 15, 14, 30, 45)
        >>> formatter.format(date)
        '2024-01-15 14:30:45'
    """
    fmt = format_string or self.default_format
    return date.strftime(fmt)
relative_time
relative_time(date: datetime) -> str

Get relative time string (e.g., "2 hours ago").

Parameters:

Name Type Description Default
date datetime

The datetime to compare against now

required

Returns:

Type Description
str

Human-readable relative time string

Example

formatter = DateFormatter() past = datetime.now() - timedelta(hours=2) formatter.relative_time(past) '2 hours ago'

Source code in src/example/utils.py
def relative_time(self, date: datetime) -> str:
    """Get relative time string (e.g., "2 hours ago").

    Args:
        date: The datetime to compare against now

    Returns:
        Human-readable relative time string

    Example:
        >>> formatter = DateFormatter()
        >>> past = datetime.now() - timedelta(hours=2)
        >>> formatter.relative_time(past)
        '2 hours ago'
    """
    now = datetime.now()
    delta = now - date

    seconds = delta.total_seconds()

    if seconds < 60:
        return "just now"
    elif seconds < 3600:
        minutes = int(seconds / 60)
        return f"{minutes} minute{'s' if minutes != 1 else ''} ago"
    elif seconds < 86400:
        hours = int(seconds / 3600)
        return f"{hours} hour{'s' if hours != 1 else ''} ago"
    else:
        days = int(seconds / 86400)
        return f"{days} day{'s' if days != 1 else ''} ago"
parse_iso staticmethod
parse_iso(date_string: str) -> datetime

Parse ISO format date string.

Parameters:

Name Type Description Default
date_string str

ISO format date string

required

Returns:

Type Description
datetime

Parsed datetime object

Raises:

Type Description
ValueError

If date string is invalid

Example

DateFormatter.parse_iso("2024-01-15T14:30:45") datetime.datetime(2024, 1, 15, 14, 30, 45)

Source code in src/example/utils.py
@staticmethod
def parse_iso(date_string: str) -> datetime:
    """Parse ISO format date string.

    Args:
        date_string: ISO format date string

    Returns:
        Parsed datetime object

    Raises:
        ValueError: If date string is invalid

    Example:
        >>> DateFormatter.parse_iso("2024-01-15T14:30:45")
        datetime.datetime(2024, 1, 15, 14, 30, 45)
    """
    return datetime.fromisoformat(date_string)

Functions

timer
timer(func: F) -> F

Decorator to measure function execution time.

This decorator wraps a function and prints the time taken to execute it.

Parameters:

Name Type Description Default
func F

The function to time

required

Returns:

Type Description
F

Wrapped function that prints execution time

Example
@timer
def slow_function():
    time.sleep(1)
    return "Done"

result = slow_function()
# Output: slow_function took 1.0012 seconds
Note

The timing includes all operations within the function, including any I/O operations.

Source code in src/example/utils.py
def timer(func: F) -> F:
    """Decorator to measure function execution time.

    This decorator wraps a function and prints the time taken
    to execute it.

    Args:
        func: The function to time

    Returns:
        Wrapped function that prints execution time

    Example:
        ```python
        @timer
        def slow_function():
            time.sleep(1)
            return "Done"

        result = slow_function()
        # Output: slow_function took 1.0012 seconds
        ```

    Note:
        The timing includes all operations within the function,
        including any I/O operations.
    """

    @functools.wraps(func)
    def wrapper(*args: Any, **kwargs: Any) -> Any:
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f} seconds")
        return result

    return wrapper  # type: ignore
format_number
format_number(number: Union[int, float], decimals: int = 2, thousands_separator: bool = True) -> str

Format a number for display.

Parameters:

Name Type Description Default
number Union[int, float]

The number to format

required
decimals int

Number of decimal places (default: 2)

2
thousands_separator bool

Whether to use thousands separator (default: True)

True

Returns:

Type Description
str

Formatted number as string

Example

format_number(1234567.89) '1,234,567.89' format_number(1234567.89, decimals=0) '1,234,568' format_number(1234.5, thousands_separator=False) '1234.50'

See Also
  • :func:validate_input: Validate numeric input
  • locale.format_string: For locale-specific formatting
Source code in src/example/utils.py
def format_number(
    number: Union[int, float], decimals: int = 2, thousands_separator: bool = True
) -> str:
    """Format a number for display.

    Args:
        number: The number to format
        decimals: Number of decimal places (default: 2)
        thousands_separator: Whether to use thousands separator (default: True)

    Returns:
        Formatted number as string

    Example:
        >>> format_number(1234567.89)
        '1,234,567.89'
        >>> format_number(1234567.89, decimals=0)
        '1,234,568'
        >>> format_number(1234.5, thousands_separator=False)
        '1234.50'

    See Also:
        - :func:`validate_input`: Validate numeric input
        - `locale.format_string`: For locale-specific formatting
    """
    if thousands_separator:
        return f"{number:,.{decimals}f}"
    else:
        return f"{number:.{decimals}f}"
validate_input
validate_input(value: Any, expected_type: type, min_value: Optional[Union[int, float]] = None, max_value: Optional[Union[int, float]] = None, allow_none: bool = False) -> bool

Validate input value against constraints.

This function checks if a value meets specified type and range constraints.

Parameters:

Name Type Description Default
value Any

The value to validate

required
expected_type type

Expected type of the value

required
min_value Optional[Union[int, float]]

Minimum allowed value (for numeric types)

None
max_value Optional[Union[int, float]]

Maximum allowed value (for numeric types)

None
allow_none bool

Whether None is a valid value

False

Returns:

Type Description
bool

True if value is valid, False otherwise

Example

validate_input(42, int, min_value=0, max_value=100) True validate_input(-5, int, min_value=0) False validate_input(None, str, allow_none=True) True

Warning

This function only performs basic validation. For complex validation logic, consider using a dedicated validation library like pydantic or cerberus.

Source code in src/example/utils.py
def validate_input(
    value: Any,
    expected_type: type,
    min_value: Optional[Union[int, float]] = None,
    max_value: Optional[Union[int, float]] = None,
    allow_none: bool = False,
) -> bool:
    """Validate input value against constraints.

    This function checks if a value meets specified type and range
    constraints.

    Args:
        value: The value to validate
        expected_type: Expected type of the value
        min_value: Minimum allowed value (for numeric types)
        max_value: Maximum allowed value (for numeric types)
        allow_none: Whether None is a valid value

    Returns:
        True if value is valid, False otherwise

    Example:
        >>> validate_input(42, int, min_value=0, max_value=100)
        True
        >>> validate_input(-5, int, min_value=0)
        False
        >>> validate_input(None, str, allow_none=True)
        True

    Warning:
        This function only performs basic validation. For complex
        validation logic, consider using a dedicated validation library
        like `pydantic` or `cerberus`.
    """
    if value is None:
        return allow_none

    if not isinstance(value, expected_type):
        return False

    if expected_type in (int, float):
        if min_value is not None and value < min_value:
            return False
        if max_value is not None and value > max_value:
            return False

    return True