CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-reuse

A tool for compliance with the REUSE recommendations for software licensing and copyright management.

Pending
Overview
Eval results
Files

comment-handling.mddocs/

Comment Handling System

REUSE provides an extensible comment processing system that supports 25+ file types for adding and parsing copyright headers. The system automatically detects comment styles and provides utilities for managing comment-based REUSE information.

Capabilities

Comment Style Detection

Automatically detect and retrieve appropriate comment styles for files.

def get_comment_style(path: StrPath) -> Optional[Type[CommentStyle]]:
    """
    Detect comment style for file path.
    
    Args:
        path: File path to analyze (accepts str or Path-like)
        
    Returns:
        CommentStyle class appropriate for the file type, or None if unsupported
        
    Note:
        Detection is based on file extension and content analysis.
        Returns the most appropriate comment style class for the file.
    """

def is_uncommentable(path: Path) -> bool:
    """
    Check if file cannot have comments added.
    
    Args:
        path: File path to check
        
    Returns:
        True if file type doesn't support comments (e.g., binary files)
    """

def has_style(path: Path) -> bool:
    """
    Check if path has a known comment style.
    
    Args:
        path: File path to check
        
    Returns:
        True if a comment style exists for this file type
    """

Usage Examples:

from reuse.comment import get_comment_style, is_uncommentable, has_style
from pathlib import Path

# Detect comment style for different file types
python_file = Path("example.py")
c_file = Path("example.c")
html_file = Path("example.html")

# Get comment styles
python_style = get_comment_style(python_file)
c_style = get_comment_style(c_file)
html_style = get_comment_style(html_file)

print(f"Python style: {python_style.__name__ if python_style else 'None'}")
print(f"C style: {c_style.__name__ if c_style else 'None'}")
print(f"HTML style: {html_style.__name__ if html_style else 'None'}")

# Check if files can be commented
print(f"Can comment Python: {not is_uncommentable(python_file)}")
print(f"Python has style: {has_style(python_file)}")

# Check binary file
binary_file = Path("example.png")
print(f"Can comment PNG: {not is_uncommentable(binary_file)}")

Base Comment Style Class

The foundation class for all comment style implementations.

class CommentStyle:
    """
    Base class for different file comment styles.
    
    Subclasses implement specific comment syntax for different file types.
    Each style defines how to create single-line and multi-line comments
    appropriate for the file format.
    """
    
    # Class attributes defined by subclasses:
    SHORTHAND: str = ""                         # Short identifier for the style  
    SINGLE_LINE: str = ""                       # Single-line comment prefix
    SINGLE_LINE_REGEXP: Optional[re.Pattern] = None  # Regex for parsing single-line comments
    INDENT_AFTER_SINGLE: str = ""               # Indentation after single-line prefix
    MULTI_LINE: MultiLineSegments = MultiLineSegments("", "", "")  # Multi-line comment structure
    INDENT_BEFORE_MIDDLE: str = ""              # Indentation before middle marker
    INDENT_AFTER_MIDDLE: str = ""               # Indentation after middle marker  
    INDENT_BEFORE_END: str = ""                 # Indentation before end marker
    SHEBANGS: list[str] = []                    # Supported shebang patterns
    
    @classmethod
    def can_handle_single(cls) -> bool:
        """Whether the CommentStyle can handle single-line comments."""
    
    @classmethod
    def can_handle_multi(cls) -> bool:
        """Whether the CommentStyle can handle multi-line comments."""
    
    @classmethod
    def create_comment(cls, text: str, force_multi: bool = False) -> str:
        """Comment all lines in text. Single-line comments are preferred unless force_multi is True.
        
        Raises:
            CommentCreateError: if text could not be commented.
        """
    
    @classmethod
    def parse_comment(cls, text: str) -> str:
        """Parse and extract comment content from commented text.
        
        Raises:
            CommentParseError: if text could not be parsed.
        """
    
    @classmethod
    def comment_at_first_character(cls, text: str) -> str:
        """Create comment starting at the first character of text."""

Multi-line Comment Structure

Data structure for multi-line comment formatting.

class MultiLineSegments(NamedTuple):
    """
    Structure for multi-line comment formatting.
    
    Attributes:
        start: str - Start marker for multi-line comment
        middle: str - Middle prefix for each line in multi-line comment  
        end: str - End marker for multi-line comment
    """
    start: str
    middle: str
    end: str

Usage Examples:

from reuse.comment import MultiLineSegments, CommentStyle

# Example multi-line segments for C-style comments
c_multiline = MultiLineSegments(
    start="/*",
    middle=" *",
    end=" */"
)

print(f"C comment start: {c_multiline.start}")
print(f"C comment middle: {c_multiline.middle}")
print(f"C comment end: {c_multiline.end}")

Supported Comment Styles

The system provides built-in support for 25+ file types through specialized comment style classes.

# Programming Languages
class PythonCommentStyle(CommentStyle):
    """Python files (.py) - # single-line comments"""
    pass

class CCommentStyle(CommentStyle):
    """C files (.c, .h) - /* multi-line */ comments"""
    pass

class CppCommentStyle(CommentStyle):
    """C++ files (.cpp, .hpp) - /* multi-line */ comments"""
    pass

class CppSingleCommentStyle(CommentStyle):
    """C++ files - // single-line comments"""
    pass

class JavaCommentStyle(CommentStyle):
    """Java files (.java) - /* multi-line */ and // single-line"""
    pass

class HaskellCommentStyle(CommentStyle):
    """Haskell files (.hs) - -- single-line comments"""
    pass

class JuliaCommentStyle(CommentStyle):
    """Julia files (.jl) - # single-line comments"""
    pass

class FortranCommentStyle(CommentStyle):
    """Fortran files (.f, .for) - C or * in column 1"""
    pass

class ModernFortranCommentStyle(CommentStyle):
    """Modern Fortran files (.f90, .f95) - ! single-line comments"""
    pass

class LispCommentStyle(CommentStyle):
    """Lisp files (.lisp, .cl) - ; single-line comments"""
    pass

class MlCommentStyle(CommentStyle):
    """ML files (.ml, .mli) - (* multi-line *) comments"""
    pass

class LeanCommentStyle(CommentStyle):
    """Lean files (.lean) - -- single-line comments"""
    pass

# Markup and Templates
class HtmlCommentStyle(CommentStyle):
    """HTML files (.html, .htm) - <!-- multi-line --> comments"""
    pass

class JinjaCommentStyle(CommentStyle):
    """Jinja templates (.j2, .jinja) - {# multi-line #} comments"""
    pass

class HandlebarsCommentStyle(CommentStyle):
    """Handlebars templates (.hbs) - {{! multi-line }} comments"""
    pass

class VelocityCommentStyle(CommentStyle):
    """Velocity templates (.vm) - ## single-line comments"""
    pass

class TexCommentStyle(CommentStyle):
    """TeX/LaTeX files (.tex, .sty) - % single-line comments"""
    pass

class ReStructedTextCommentStyle(CommentStyle):
    """reStructuredText files (.rst) - .. single-line comments"""
    pass

# Configuration and Data
class BibTexCommentStyle(CommentStyle):
    """BibTeX files (.bib) - % single-line comments"""
    pass

class M4CommentStyle(CommentStyle):
    """M4 files (.m4) - dnl single-line comments"""
    pass

class FtlCommentStyle(CommentStyle):
    """FTL files (.ftl) - <#-- multi-line --> comments"""
    pass

# Scripting and System
class BatchFileCommentStyle(CommentStyle):
    """Batch files (.bat, .cmd) - REM single-line comments"""
    pass

class AppleScriptCommentStyle(CommentStyle):
    """AppleScript files (.scpt) - -- single-line comments"""
    pass

class VimCommentStyle(CommentStyle):
    """Vim script files (.vim) - \" single-line comments"""
    pass

class UnixManCommentStyle(CommentStyle):
    """Unix manual pages (.1, .2, etc.) - .\\\" single-line comments"""
    pass

# Other Formats
class AspxCommentStyle(CommentStyle):
    """ASPX files (.aspx) - <%-- multi-line --%> comments"""
    pass

class XQueryCommentStyle(CommentStyle):
    """XQuery files (.xq, .xquery) - (: multi-line :) comments"""
    pass

class PlantUmlCommentStyle(CommentStyle):
    """PlantUML files (.puml) - ' single-line comments"""
    pass

class SemicolonCommentStyle(CommentStyle):
    """Files using semicolon comments - ; single-line comments"""
    pass

# Special Cases
class EmptyCommentStyle(CommentStyle):
    """Files that support comments but with empty prefix"""
    pass

class UncommentableCommentStyle(CommentStyle):
    """Files that cannot have comments (binary files, etc.)"""
    pass

Comment Style Registry

Access the mapping between style names and comment style classes.

NAME_STYLE_MAP: dict[str, Type[CommentStyle]]
"""Dictionary mapping style names to comment style classes."""

Usage Examples:

from reuse.comment import NAME_STYLE_MAP

# List all available comment styles
print("Available comment styles:")
for name, style_class in NAME_STYLE_MAP.items():
    print(f"  {name}: {style_class.__name__}")

# Get specific style by name
python_style = NAME_STYLE_MAP.get("python")
if python_style:
    print(f"Python style class: {python_style.__name__}")

# Check if style exists
has_rust_style = "rust" in NAME_STYLE_MAP
print(f"Has Rust style: {has_rust_style}")

Comment Style Usage Examples

Working with Different Comment Styles

from reuse.comment import get_comment_style, PythonCommentStyle, CCommentStyle
from pathlib import Path

def demonstrate_comment_styles():
    """Demonstrate comment style detection and usage."""
    
    # File type detection
    files = [
        Path("example.py"),
        Path("example.c"), 
        Path("example.html"),
        Path("example.js"),
        Path("example.tex")
    ]
    
    for file_path in files:
        style_class = get_comment_style(file_path)
        if style_class:
            print(f"\n{file_path.suffix} files use: {style_class.__name__}")
            
            # Create style instance
            style = style_class()
            
            # Show single-line comment prefix
            if hasattr(style, 'SINGLE_LINE') and style.SINGLE_LINE:
                print(f"  Single-line: '{style.SINGLE_LINE}'")
            
            # Show multi-line comment structure
            if hasattr(style, 'MULTI_LINE') and style.MULTI_LINE:
                ml = style.MULTI_LINE
                print(f"  Multi-line: '{ml.start}' ... '{ml.middle}' ... '{ml.end}'")

demonstrate_comment_styles()

Creating Custom Comment Headers

from reuse.comment import get_comment_style, MultiLineSegments
from pathlib import Path

def create_comment_header(file_path: Path, copyright_text: str, license_id: str) -> str:
    """Create a properly formatted comment header for a file."""
    
    style_class = get_comment_style(file_path)
    if not style_class:
        return ""
    
    style = style_class()
    
    # Prepare header content
    header_lines = [
        f"SPDX-FileCopyrightText: {copyright_text}",
        f"SPDX-License-Identifier: {license_id}"
    ]
    
    # Format based on comment style
    if hasattr(style, 'MULTI_LINE') and style.MULTI_LINE:
        # Use multi-line comment format
        ml = style.MULTI_LINE
        formatted_lines = [ml.start]
        for line in header_lines:
            formatted_lines.append(f"{ml.middle} {line}")
        formatted_lines.append(ml.end)
        return "\n".join(formatted_lines)
    
    elif hasattr(style, 'SINGLE_LINE') and style.SINGLE_LINE:
        # Use single-line comment format
        prefix = style.SINGLE_LINE
        indent = getattr(style, 'INDENT_AFTER_SINGLE', ' ')
        formatted_lines = []
        for line in header_lines:
            formatted_lines.append(f"{prefix}{indent}{line}")
        return "\n".join(formatted_lines)
    
    return ""

# Usage examples
python_header = create_comment_header(
    Path("example.py"),
    "2023 Jane Doe <jane@example.com>",
    "MIT"
)
print("Python header:")
print(python_header)

c_header = create_comment_header(
    Path("example.c"),
    "2023 Jane Doe <jane@example.com>", 
    "GPL-3.0-or-later"
)
print("\nC header:")
print(c_header)

File Type Comment Style Reference

from reuse.comment import get_comment_style
from pathlib import Path

def show_comment_reference():
    """Show comment styles for common file types."""
    
    file_extensions = [
        ".py", ".c", ".cpp", ".java", ".rs", ".go", ".js", ".ts",
        ".html", ".css", ".scss", ".php", ".rb", ".pl", ".sh",
        ".tex", ".md", ".rst", ".yaml", ".json", ".xml", ".sql"
    ]
    
    print("File Type Comment Style Reference:")
    print("=" * 50)
    
    for ext in file_extensions:
        test_file = Path(f"test{ext}")
        style_class = get_comment_style(test_file)
        
        if style_class:
            style = style_class()
            comment_info = []
            
            if hasattr(style, 'SINGLE_LINE') and style.SINGLE_LINE:
                comment_info.append(f"single: '{style.SINGLE_LINE}'")
            
            if hasattr(style, 'MULTI_LINE') and style.MULTI_LINE:
                ml = style.MULTI_LINE
                comment_info.append(f"multi: '{ml.start}...{ml.end}'")
            
            print(f"{ext:8} -> {style_class.__name__:25} ({', '.join(comment_info)})")
        else:
            print(f"{ext:8} -> No comment style available")

show_comment_reference()

Install with Tessl CLI

npx tessl i tessl/pypi-reuse

docs

cli.md

comment-handling.md

global-licensing.md

index.md

project-management.md

report-generation.md

reuse-info.md

vcs-integration.md

tile.json