CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-safety

Scan dependencies for known vulnerabilities and licenses.

Overall
score

61%

Overview
Eval results
Files

formatters.mddocs/

Output and Formatters

Safety CLI provides a comprehensive formatting and output system that supports multiple report formats for vulnerability scanning, license checking, and other analysis results. The system uses a strategy pattern with pluggable formatters for different output types.

Core Formatter Architecture

FormatterAPI Base Class { .api }

Import Statements:

from safety.formatter import FormatterAPI, SafetyFormatter
from safety.formatters.json import JsonReport, build_json_report
from safety.formatters.text import TextReport
from safety.formatters.screen import ScreenReport
from safety.formatters.html import HTMLReport
from safety.formatters.bare import BareReport
from safety.models import SafetyEncoder

FormatterAPI Abstract Base { .api }

Description: Abstract base class defining the interface for all output formatters.

class FormatterAPI:
    """Strategy pattern base class for report formatters."""
    
    def __init__(self, **kwargs: Any) -> None:
        """
        Initialize formatter with configuration options.
        
        Args:
            **kwargs: Formatter-specific configuration options
        """
        
    @abstractmethod
    def render_vulnerabilities(
        self,
        announcements: List[Dict[str, Any]],        # Platform announcements
        vulnerabilities: List[Dict[str, Any]],      # Found vulnerabilities
        remediations: Dict[str, Any],               # Remediation suggestions
        full: bool,                                 # Include full details
        packages: List[Dict[str, Any]],             # Scanned packages
        fixes: Tuple = ()                           # Applied fixes
    ) -> Optional[str]:
        """
        Render vulnerability scan results.
        
        Args:
            announcements: Platform announcements and notices
            vulnerabilities: Detected vulnerabilities
            remediations: Available remediation options
            full: Whether to include detailed information
            packages: List of analyzed packages
            fixes: Applied automatic fixes
            
        Returns:
            Optional[str]: Formatted report output
        """
        
    @abstractmethod
    def render_licenses(
        self,
        announcements: List[Dict[str, Any]],        # Platform announcements
        licenses: List[Dict[str, Any]]              # License information
    ) -> Optional[str]:
        """
        Render license compliance report.
        
        Args:
            announcements: Platform announcements
            licenses: Package license information
            
        Returns:
            Optional[str]: Formatted license report
        """
        
    @abstractmethod
    def render_announcements(
        self,
        announcements: List[Dict[str, Any]]         # Platform announcements
    ) -> Optional[str]:
        """
        Render platform announcements.
        
        Args:
            announcements: Platform announcements and notices
            
        Returns:
            Optional[str]: Formatted announcements
        """

SafetyFormatter Factory { .api }

Description: Factory class that creates appropriate formatter instances based on output format specification.

class SafetyFormatter(FormatterAPI):
    """Factory formatter that delegates to specific format implementations."""
    
    def __init__(self, output: str, **kwargs: Any) -> None:
        """
        Initialize formatter factory with target output format.
        
        Args:
            output (str): Target output format ('json', 'html', 'bare', 'text', 'screen')
            **kwargs: Additional configuration passed to specific formatter
        """
        
    # Supported output formats
    SUPPORTED_FORMATS = [
        'json',      # Machine-readable JSON
        'html',      # Web-viewable HTML report
        'bare',      # Minimal text output
        'text',      # Formatted text report
        'screen'     # Rich terminal output (default)
    ]

Example Usage:

from safety.formatter import SafetyFormatter

# Create JSON formatter
json_formatter = SafetyFormatter(output='json')

# Create HTML formatter with custom template
html_formatter = SafetyFormatter(
    output='html',
    template_dir='/custom/templates'
)

# Create screen formatter for terminal output
screen_formatter = SafetyFormatter(output='screen')

Format-Specific Implementations

JSON Formatter { .api }

JsonReport Class { .api }

Description: Generates machine-readable JSON reports for vulnerability and license data.

class JsonReport(FormatterAPI):
    """JSON formatter for machine-readable output."""
    
    def __init__(self, version: str = "3.0", **kwargs: Any) -> None:
        """
        Initialize JSON formatter.
        
        Args:
            version (str): JSON schema version to use
            **kwargs: Additional configuration options
        """
        
    def render_vulnerabilities(
        self,
        announcements: List[Dict[str, Any]],
        vulnerabilities: List[Dict[str, Any]], 
        remediations: Dict[str, Any],
        full: bool,
        packages: List[Dict[str, Any]],
        fixes: Tuple = ()
    ) -> str:
        """
        Generate JSON vulnerability report.
        
        Returns:
            str: JSON-formatted vulnerability report
        """
        
    def render_licenses(
        self,
        announcements: List[Dict[str, Any]],
        licenses: List[Dict[str, Any]]
    ) -> str:
        """
        Generate JSON license report.
        
        Returns:
            str: JSON-formatted license report
        """

JSON Report Builder { .api }

def build_json_report(
    announcements: List[Dict],                      # Platform announcements
    vulnerabilities: List[Dict],                    # Vulnerability data
    remediations: Dict[str, Any],                   # Remediation options
    packages: List[Any]                             # Package information
) -> Dict[str, Any]:
    """
    Build structured JSON report from scan results.
    
    Args:
        announcements: Platform announcements and notices
        vulnerabilities: Detected vulnerabilities
        remediations: Available remediation suggestions
        packages: Scanned package information
        
    Returns:
        Dict[str, Any]: Structured report data ready for JSON serialization
    """

JSON Report Structure:

{
    "report_meta": {
        "scan_target": "project_directory",
        "timestamp": "2024-01-15T10:30:00Z",
        "safety_version": "3.6.1",
        "vulnerabilities_found": 2,
        "vulnerabilities_ignored": 1,
        "remediations_recommended": 1
    },
    "vulnerabilities": [
        {
            "vulnerability_id": "VULN-12345",
            "package_name": "requests",
            "installed_version": "2.20.0",
            "affected_versions": ">=2.0.0,<2.20.1",
            "advisory": "Security vulnerability description",
            "cve": {
                "name": "CVE-2023-12345", 
                "cvssv3": 7.5
            },
            "severity": {
                "source": "safety",
                "cvssv3": 7.5
            },
            "fixed_versions": ["2.20.1", "2.21.0"],
            "ignored": false,
            "more_info_url": "https://safety.com/vuln/12345"
        }
    ],
    "ignored_vulnerabilities": [...],
    "remediations": {...},
    "packages": [...],
    "announcements": [...]
}

Screen Formatter { .api }

ScreenReport Class { .api }

Description: Rich terminal formatter with colors, formatting, and interactive elements.

class ScreenReport(FormatterAPI):
    """Rich terminal formatter for interactive console output."""
    
    def __init__(self, 
                 console=None,                      # Rich console instance
                 emoji: bool = True,                # Enable emoji output
                 **kwargs: Any) -> None:
        """
        Initialize screen formatter.
        
        Args:
            console: Rich console instance for output
            emoji: Enable emoji in output
            **kwargs: Additional configuration
        """
        
    def render_vulnerabilities(self, ...) -> str:
        """
        Generate rich terminal vulnerability report with:
        - Color-coded severity levels
        - Formatted tables and lists
        - Progress indicators
        - Interactive elements
        """
        
    def render_licenses(self, ...) -> str:
        """Generate formatted license compliance report."""

Screen Output Features:

  • Color Coding: Severity-based color schemes (red=critical, orange=high, etc.)
  • Rich Formatting: Tables, lists, and structured layout
  • Emoji Support: Visual indicators for status and severity
  • Progress Indicators: Real-time scan progress
  • Interactive Elements: Clickable links and expandable sections

Text Formatter { .api }

TextReport Class { .api }

Description: Plain text formatter for non-interactive environments and file output.

class TextReport(FormatterAPI):
    """Plain text formatter for file output and non-interactive terminals."""
    
    def render_vulnerabilities(self, ...) -> str:
        """
        Generate plain text vulnerability report suitable for:
        - File output
        - Email reports
        - CI/CD logs
        - Non-interactive terminals
        """
        
    def render_licenses(self, ...) -> str:
        """Generate plain text license report."""

HTML Formatter { .api }

HTMLReport Class { .api }

Description: HTML formatter for web-viewable reports with styling and interactivity.

class HTMLReport(FormatterAPI):
    """HTML formatter for web-viewable vulnerability reports."""
    
    def __init__(self, 
                 template_dir: Optional[str] = None,    # Custom template directory
                 **kwargs: Any) -> None:
        """
        Initialize HTML formatter.
        
        Args:
            template_dir: Custom Jinja2 template directory
            **kwargs: Additional template variables
        """
        
    def render_vulnerabilities(self, ...) -> str:
        """
        Generate HTML vulnerability report with:
        - Styled tables and layouts  
        - Interactive filtering
        - Sortable columns
        - Embedded CSS and JavaScript
        """

HTML Report Features:

  • Responsive Design: Mobile and desktop compatible
  • Interactive Tables: Sortable and filterable vulnerability lists
  • Severity Styling: Color-coded severity indicators
  • Embedded Assets: Self-contained HTML files
  • Print Optimized: Clean printing layouts

Bare Formatter { .api }

BareReport Class { .api }

Description: Minimal formatter for machine processing and scripting integration.

class BareReport(FormatterAPI):
    """Minimal formatter for machine processing and automation."""
    
    def render_vulnerabilities(self, ...) -> str:
        """
        Generate minimal vulnerability output:
        - One vulnerability per line
        - Tab or delimiter-separated fields
        - No headers or formatting
        - Suitable for grep, awk, etc.
        """
        
    def render_licenses(self, ...) -> str:
        """Generate minimal license output."""

Bare Output Format:

package_name\tvulnerability_id\tseverity\tinstalled_version\tfixed_version
requests\tVULN-12345\thigh\t2.20.0\t2.20.1
django\tVULN-67890\tcritical\t3.0.0\t3.0.14

Data Encoding and Serialization

SafetyEncoder { .api }

Description: Custom JSON encoder for Safety-specific data types and models.

from safety.models import SafetyEncoder

class SafetyEncoder(json.JSONEncoder):
    """Custom JSON encoder for Safety data structures."""
    
    def default(self, obj: Any) -> Any:
        """
        Serialize Safety-specific objects to JSON-compatible formats.
        
        Handles:
        - Vulnerability objects
        - Package objects  
        - DateTime objects
        - Custom data classes
        
        Args:
            obj: Object to serialize
            
        Returns:
            Any: JSON-serializable representation
        """

Example Usage:

import json
from safety.models import SafetyEncoder

# Serialize vulnerability data with custom encoder
vulnerability_data = {...}  # Vulnerability objects
json_output = json.dumps(
    vulnerability_data,
    cls=SafetyEncoder,
    indent=2
)

Output Utilities and Helpers

Report Brief Information { .api }

from safety.output_utils import get_report_brief_info, should_add_nl

def get_report_brief_info(
    as_dict: bool = False,                          # Return as dictionary
    report_type: int = 1,                          # Report type identifier
    vulnerabilities_found: int = 0,                 # Number of vulnerabilities
    vulnerabilities_ignored: int = 0,               # Number ignored
    remediations_recommended: Dict = None           # Remediation suggestions
) -> Union[str, Dict[str, Any]]:
    """
    Generate brief report summary information.
    
    Args:
        as_dict: Return structured data instead of formatted string
        report_type: Type of report (1=vulnerability, 2=license, etc.)
        vulnerabilities_found: Count of active vulnerabilities
        vulnerabilities_ignored: Count of ignored vulnerabilities
        remediations_recommended: Available remediation options
        
    Returns:
        Union[str, Dict]: Brief report summary
    """

def should_add_nl(console_output: str) -> bool:
    """
    Determine if newline should be added to console output.
    
    Args:
        console_output (str): Console output string
        
    Returns:
        bool: True if newline should be added
    """

Schema Versioning { .api }

Report Schemas { .api }

Safety supports versioned report schemas for backward compatibility:

from safety.formatters.schemas.v3_0 import ScanReportV30

class ScanReportV30(BaseModel):
    """Pydantic model for v3.0 scan report schema."""
    
    report_meta: ReportMeta                         # Report metadata
    vulnerabilities: List[VulnerabilityModel]      # Vulnerability findings
    ignored_vulnerabilities: List[VulnerabilityModel]  # Ignored vulnerabilities  
    remediations: Dict[str, Any]                   # Remediation suggestions
    packages: List[PackageModel]                   # Scanned packages
    announcements: List[AnnouncementModel]         # Platform announcements

Configuration and Customization

Formatter Configuration { .api }

Formatters can be configured through various options:

# JSON formatter with specific version
json_formatter = SafetyFormatter(
    output='json',
    version='3.0',
    indent=4,
    sort_keys=True
)

# HTML formatter with custom templates
html_formatter = SafetyFormatter(
    output='html',
    template_dir='/path/to/custom/templates',
    theme='dark',
    include_css=True
)

# Screen formatter with custom console
from rich.console import Console
custom_console = Console(width=120, theme='github-dark')

screen_formatter = SafetyFormatter(
    output='screen',
    console=custom_console,
    emoji=False
)

Template Customization { .api }

HTML formatter supports custom Jinja2 templates:

<!-- Custom vulnerability report template -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ report_title }} - Security Report</title>
    <style>{{ embedded_css }}</style>
</head>
<body>
    <h1>{{ report_title }}</h1>
    
    {% if vulnerabilities %}
    <table class="vulnerabilities">
        <thead>
            <tr>
                <th>Package</th>
                <th>Vulnerability</th>
                <th>Severity</th>
                <th>Fixed Version</th>
            </tr>
        </thead>
        <tbody>
            {% for vuln in vulnerabilities %}
            <tr class="severity-{{ vuln.severity.lower() }}">
                <td>{{ vuln.package_name }}</td>
                <td>{{ vuln.vulnerability_id }}</td>
                <td>{{ vuln.severity }}</td>
                <td>{{ vuln.fixed_versions|join(', ') }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
    {% endif %}
</body>
</html>

Usage Examples

Basic Report Generation

from safety.formatter import SafetyFormatter

# Sample data
vulnerabilities = [...]  # Vulnerability objects
packages = [...]         # Package objects
announcements = [...]    # Announcement objects
remediations = {...}     # Remediation suggestions

# Generate JSON report
json_formatter = SafetyFormatter(output='json')
json_report = json_formatter.render_vulnerabilities(
    announcements=announcements,
    vulnerabilities=vulnerabilities,
    remediations=remediations,
    full=True,
    packages=packages
)

# Save to file
with open('security-report.json', 'w') as f:
    f.write(json_report)

Multi-Format Reporting

from safety.formatter import SafetyFormatter

# Generate reports in multiple formats
formats = ['json', 'html', 'text']
reports = {}

for format_type in formats:
    formatter = SafetyFormatter(output=format_type)
    reports[format_type] = formatter.render_vulnerabilities(
        announcements=announcements,
        vulnerabilities=vulnerabilities, 
        remediations=remediations,
        full=True,
        packages=packages
    )

# Save each format
for format_type, content in reports.items():
    filename = f'security-report.{format_type}'
    with open(filename, 'w') as f:
        f.write(content)

License Reporting

# Generate license compliance report
license_data = [...]  # License information

formatter = SafetyFormatter(output='html')
license_report = formatter.render_licenses(
    announcements=announcements,
    licenses=license_data
)

# Display in terminal
formatter = SafetyFormatter(output='screen')
terminal_output = formatter.render_licenses(
    announcements=announcements,
    licenses=license_data
)
print(terminal_output)

Custom JSON Processing

from safety.formatters.json import build_json_report
import json

# Build structured report data
report_data = build_json_report(
    announcements=announcements,
    vulnerabilities=vulnerabilities,
    remediations=remediations,
    packages=packages
)

# Custom processing
report_data['custom_metadata'] = {
    'scan_time': datetime.now().isoformat(),
    'project_name': 'my-project',
    'environment': 'production'
}

# Serialize with custom options
json_output = json.dumps(
    report_data,
    cls=SafetyEncoder,
    indent=2,
    sort_keys=True,
    ensure_ascii=False
)

This comprehensive formatter documentation covers all aspects of Safety CLI's output and formatting system, enabling developers to generate reports in their preferred format and integrate security scanning results into their workflows and tooling.

Install with Tessl CLI

npx tessl i tessl/pypi-safety

docs

authentication.md

cli-commands.md

configuration.md

errors.md

formatters.md

index.md

models.md

programmatic.md

scanning.md

tile.json