🔍 Code Extractor

class SignatureManager

Maturity: 48

A class that manages digital signature images for documents, providing functionality to store, retrieve, and list signature files in a designated directory.

File:
/tf/active/vicechatdev/document_auditor/src/security/signature_manager.py
Lines:
6 - 141
Complexity:
moderate

Purpose

The SignatureManager class handles the lifecycle of digital signature images used in document signing workflows. It provides methods to add new signatures, retrieve existing signatures by signer name, and list all available signatures. The class automatically handles file naming conventions, directory creation, image format conversion, and provides fallback mechanisms for finding signatures with alternative naming patterns. It's designed to be used in document processing systems where digital signatures need to be applied to PDFs or other document formats.

Source Code

class SignatureManager:
    """Manages digital signatures for documents"""
    
    def __init__(self, signatures_dir="signatures"):
        """
        Initialize the signature manager
        
        Args:
            signatures_dir (str): Path to directory containing signature images
        """
        self.logger = logging.getLogger(__name__)
        self.signatures_dir = signatures_dir
        
        # Ensure the signatures directory exists
        if not os.path.isdir(self.signatures_dir):
            os.makedirs(self.signatures_dir, exist_ok=True)
            self.logger.info(f"Created signatures directory: {self.signatures_dir}")
    
    def get_signature_path(self, name):
        """
        Get the path to a signature image for a given name
        
        Args:
            name (str): Name of the person whose signature to retrieve
            
        Returns:
            str: Path to signature image if found, None otherwise
        """
        # Convert the name to a filename (lowercase, spaces to underscores)
        filename = name.lower().replace(" ", "_") + ".png"
        signature_path = os.path.join(self.signatures_dir, filename)
        
        if os.path.exists(signature_path):
            self.logger.debug(f"Found signature for {name}: {signature_path}")
            return signature_path
        else:
            self.logger.warning(f"No signature found for {name} (looked for {signature_path})")
            
            # Try alternative filenames
            alt_filenames = [
                name.lower().replace(" ", "-") + ".png",  # with hyphens
                name.replace(" ", "") + ".png",           # no spaces
                "_".join(name.lower().split()) + ".png",  # with underscores
                name + ".png"                             # exact name
            ]
            
            for alt_filename in alt_filenames:
                alt_path = os.path.join(self.signatures_dir, alt_filename)
                if os.path.exists(alt_path):
                    self.logger.info(f"Found signature with alternative name: {alt_path}")
                    return alt_path
            
            return None
    
    def add_signature(self, signer_name, signature_image_path):
        """
        Add a signature image to the signatures directory
        
        Args:
            signer_name (str): Name of the signer
            signature_image_path (str): Path to signature image
            
        Returns:
            str: Path to the saved signature image
        """
        if not os.path.exists(signature_image_path):
            raise FileNotFoundError(f"Signature image not found: {signature_image_path}")
        
        # Normalize signer name for filename
        normalized_name = self._normalize_name(signer_name)
        
        # Determine file extension
        ext = os.path.splitext(signature_image_path)[1].lower()
        if not ext or ext not in ['.png', '.jpg', '.jpeg', '.gif']:
            # Default to PNG if not a supported format
            ext = '.png'
        
        # Create destination path
        dest_path = os.path.join(self.signatures_dir, f"{normalized_name}{ext}")
        
        # Process the image - ensure it has transparency if PNG
        try:
            img = Image.open(signature_image_path)
            
            # Convert to RGBA if PNG
            if ext == '.png':
                img = img.convert('RGBA')
            
            # Save the processed image
            img.save(dest_path)
            self.logger.info(f"Added signature for {signer_name}: {dest_path}")
            
            return dest_path
        
        except Exception as e:
            self.logger.error(f"Error processing signature image: {e}")
            raise
    
    def list_available_signatures(self):
        """
        List all available signature files
        
        Returns:
            list: List of names with available signatures
        """
        signatures = []
        
        if not os.path.exists(self.signatures_dir):
            return signatures
        
        # Get all PNG files in the signatures directory
        for filename in os.listdir(self.signatures_dir):
            if filename.lower().endswith('.png'):
                # Convert filename back to a name (remove extension, replace underscores with spaces)
                name = os.path.splitext(filename)[0].replace("_", " ").title()
                signatures.append(name)
        
        return signatures

    def _normalize_name(self, name):
        """
        Normalize a name for filename use
        
        Args:
            name (str): Name to normalize
            
        Returns:
            str: Normalized name
        """
        # Replace spaces with underscores and convert to lowercase
        normalized = name.strip().replace(' ', '_').lower()
        
        # Remove special characters
        normalized = ''.join(c for c in normalized if c.isalnum() or c == '_')
        
        return normalized

Parameters

Name Type Default Kind
bases - -

Parameter Details

signatures_dir: Path to the directory where signature image files will be stored and retrieved. Defaults to 'signatures'. The directory will be created automatically if it doesn't exist. This should be a string representing either a relative or absolute path to the desired storage location.

Return Value

Instantiation returns a SignatureManager object that maintains state about the signatures directory and provides methods for signature management. Key method returns: get_signature_path() returns a string path to the signature file or None if not found; add_signature() returns the string path where the signature was saved; list_available_signatures() returns a list of strings representing available signer names; _normalize_name() returns a normalized string suitable for use as a filename.

Class Interface

Methods

__init__(self, signatures_dir='signatures')

Purpose: Initialize the SignatureManager with a directory for storing signature images

Parameters:

  • signatures_dir: Path to directory containing signature images, defaults to 'signatures'

Returns: None (constructor)

get_signature_path(self, name: str) -> str | None

Purpose: Retrieve the file path to a signature image for a given signer name, trying multiple naming conventions

Parameters:

  • name: Name of the person whose signature to retrieve

Returns: String path to the signature image file if found, None if no matching signature exists

add_signature(self, signer_name: str, signature_image_path: str) -> str

Purpose: Add a signature image to the signatures directory with proper naming and format conversion

Parameters:

  • signer_name: Name of the signer to associate with this signature
  • signature_image_path: Path to the source signature image file to be added

Returns: String path to the saved signature image in the signatures directory

list_available_signatures(self) -> list

Purpose: List all available signature files in the signatures directory

Returns: List of strings representing names with available signatures (converted from filenames to readable names)

_normalize_name(self, name: str) -> str

Purpose: Normalize a person's name for use as a filename by converting to lowercase, replacing spaces with underscores, and removing special characters

Parameters:

  • name: Name to normalize

Returns: Normalized string suitable for use as a filename

Attributes

Name Type Description Scope
logger logging.Logger Logger instance for recording debug, info, warning, and error messages during signature operations instance
signatures_dir str Path to the directory where signature image files are stored and retrieved instance

Dependencies

  • os
  • logging
  • glob
  • PIL

Required Imports

import os
import logging
import glob
from PIL import Image

Usage Example

import os
import logging
from PIL import Image

# Set up logging
logging.basicConfig(level=logging.INFO)

# Create a SignatureManager instance
sig_manager = SignatureManager(signatures_dir='./my_signatures')

# Add a new signature
try:
    saved_path = sig_manager.add_signature('John Doe', '/path/to/john_signature.png')
    print(f'Signature saved to: {saved_path}')
except FileNotFoundError as e:
    print(f'Error: {e}')

# Retrieve a signature path
signature_path = sig_manager.get_signature_path('John Doe')
if signature_path:
    print(f'Found signature at: {signature_path}')
else:
    print('Signature not found')

# List all available signatures
available = sig_manager.list_available_signatures()
print(f'Available signatures: {available}')

Best Practices

  • Always instantiate the SignatureManager with a dedicated directory path to avoid mixing signature files with other data
  • Ensure the application has write permissions to the signatures directory before instantiation
  • Use add_signature() to add new signatures rather than manually copying files to ensure proper format conversion and naming
  • The class automatically creates the signatures directory if it doesn't exist, so no pre-setup is required
  • Signature files are normalized to lowercase with underscores replacing spaces, but get_signature_path() handles multiple naming conventions automatically
  • When adding signatures, supported image formats are PNG, JPG, JPEG, and GIF; PNG is recommended for transparency support
  • The class uses logging extensively, so configure logging appropriately to capture debug, info, warning, and error messages
  • get_signature_path() tries multiple filename variations automatically, making it resilient to different naming conventions
  • The _normalize_name() method is private and should not be called directly by external code

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function main_v30 60.1% similar

    Generates sample signature images (PNG files) for a predefined list of names and saves them to a 'signatures' directory.

    From: /tf/active/vicechatdev/document_auditor/generate_sample_signatures.py
  • class SignatureGenerator 57.7% similar

    A class that generates signature-like images from text names using italic fonts and decorative flourishes.

    From: /tf/active/vicechatdev/document_auditor/src/utils/signature_generator.py
  • class SignatureImage 55.9% similar

    A ReportLab Flowable subclass for embedding signature images in PDFs with automatic fallback to placeholder text when images are unavailable or cannot be loaded.

    From: /tf/active/vicechatdev/CDocs/utils/pdf_utils.py
  • class SignatureImage_v1 55.9% similar

    A custom ReportLab Flowable class that renders signature images in PDF documents with automatic fallback to placeholder text when images are unavailable or cannot be loaded.

    From: /tf/active/vicechatdev/document_auditor/src/audit_page_generator.py
  • class DocumentProcessor 49.4% similar

    A comprehensive document processing class that converts documents to PDF, adds audit trails, applies security features (watermarks, signatures, hashing), and optionally converts to PDF/A format with document protection.

    From: /tf/active/vicechatdev/document_auditor/src/document_processor.py
← Back to Browse