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

project-management.mddocs/

Project Management and Analysis

The REUSE project management system provides core functionality for discovering, configuring, and analyzing projects for REUSE compliance. The central Project class manages project root detection, file discovery, and metadata extraction.

Capabilities

Project Creation and Configuration

Create and configure Project instances for REUSE analysis.

class Project:
    """
    Central class holding project root and configuration.
    
    Attributes:
        root: Path - Project root directory
        include_submodules: bool - Whether to include VCS submodules
        include_meson_subprojects: bool - Whether to include Meson subprojects
        vcs_strategy: VCSStrategy - VCS strategy for the project
        global_licensing: Optional[GlobalLicensing] - Global licensing configuration
        license_map: dict[str, dict] - License mapping
        licenses: dict[str, Path] - License files mapping
        licenses_without_extension: dict[str, Path] - License files without extensions
    """
    
    @classmethod
    def from_directory(
        cls,
        root: Path,
        include_submodules: bool = False,
        include_meson_subprojects: bool = False
    ) -> Project:
        """
        Factory method to create Project from directory.
        
        Args:
            root: Project root directory path
            include_submodules: Include VCS submodules in analysis
            include_meson_subprojects: Include Meson subprojects in analysis
            
        Returns:
            Project instance configured for the directory
            
        Raises:
            FileNotFoundError: If root directory doesn't exist
        """

Usage Examples:

from reuse.project import Project
from pathlib import Path

# Create project from current directory
project = Project.from_directory(Path.cwd())

# Create project with submodules included
project = Project.from_directory(
    Path("/path/to/project"),
    include_submodules=True
)

# Create project with all options
project = Project.from_directory(
    Path("/path/to/project"),
    include_submodules=True,
    include_meson_subprojects=True
)

File Discovery and Iteration

Discover and iterate over project files with intelligent filtering.

def all_files(self, directory: Optional[Path] = None) -> Iterator[Path]:
    """
    Iterator over all files in project.
    
    Args:
        directory: Optional directory to limit search (default: project root)
        
    Yields:
        Path: File paths within the project
        
    Note:
        Respects VCS ignore patterns and project configuration for submodules
        and subprojects. Files are yielded in a deterministic order.
    """

Usage Examples:

# Iterate over all project files
for file_path in project.all_files():
    print(f"Processing: {file_path}")

# Iterate over files in specific directory
src_dir = project.root / "src" 
for file_path in project.all_files(src_dir):
    print(f"Source file: {file_path}")

# Count total files
total_files = sum(1 for _ in project.all_files())
print(f"Total files: {total_files}")

REUSE Information Extraction

Extract REUSE licensing and copyright information from project files.

def reuse_info_of(self, path: Path) -> list[ReuseInfo]:
    """
    Get REUSE info for a specific file.
    
    Args:
        path: File path to analyze (absolute or relative to project root)
        
    Returns:
        List of ReuseInfo objects containing licensing and copyright data
        
    Note:
        Checks multiple sources: file headers, .license files, global
        licensing files (.reuse/dep5, REUSE.toml), and license directories.
        Returns empty list if no REUSE information is found.
    """

Usage Examples:

# Get REUSE info for a single file
file_path = Path("src/example.py")
reuse_info = project.reuse_info_of(file_path)

for info in reuse_info:
    print(f"Source: {info.source_type}")
    print(f"Licenses: {info.spdx_expressions}")
    print(f"Copyright: {info.copyright_lines}")
    print(f"Contributors: {info.contributor_lines}")

# Check if file has REUSE information
has_info = any(info.contains_info() for info in reuse_info)
print(f"Has REUSE info: {has_info}")

# Get copyright and licensing status
has_both = any(info.contains_copyright_or_licensing() for info in reuse_info)
has_one = any(info.contains_copyright_xor_licensing() for info in reuse_info)

Path Utilities

Utility methods for path manipulation within projects.

def relative_from_root(self, path: Path) -> Path:
    """
    Convert path to relative from project root.
    
    Args:
        path: Absolute or relative path
        
    Returns:
        Path relative to project root
        
    Raises:
        ValueError: If path is not within project
    """

Usage Examples:

# Convert absolute path to relative
abs_path = Path("/full/path/to/project/src/file.py")
rel_path = project.relative_from_root(abs_path)
print(rel_path)  # src/file.py

# Works with paths already relative to project
rel_path = project.relative_from_root(Path("src/file.py"))
print(rel_path)  # src/file.py

Global Licensing Discovery

Discover and access global licensing configuration files.

class GlobalLicensingFound(NamedTuple):
    """
    Result of global licensing file discovery.
    
    Attributes:
        path: Path - Path to global licensing file
        cls: Type[GlobalLicensing] - Class type of global licensing implementation
    """
    path: Path
    cls: Type[GlobalLicensing]

Usage Examples:

# Check if project has global licensing
if project.global_licensing:
    print(f"Global licensing type: {type(project.global_licensing).__name__}")
    
    # Access licensing configuration
    if hasattr(project.global_licensing, 'path'):
        print(f"Config file: {project.global_licensing.path}")

License File Management

Access and manage project license files.

# Project attributes for license management
licenses: dict[str, Path]                    # License files mapping  
licenses_without_extension: dict[str, Path]  # License files without extensions
license_map: dict[str, dict]                 # License mapping configuration

Usage Examples:

# List all license files
for spdx_id, license_path in project.licenses.items():
    print(f"{spdx_id}: {license_path}")

# Check for specific license
if "MIT" in project.licenses:
    mit_path = project.licenses["MIT"]
    print(f"MIT license at: {mit_path}")

# Access license files without extensions
for spdx_id, license_path in project.licenses_without_extension.items():
    print(f"{spdx_id}: {license_path}")

VCS Integration

Access version control system information and strategies.

# Project attribute for VCS integration
vcs_strategy: VCSStrategy  # VCS strategy for the project

Usage Examples:

# Check VCS type
vcs_name = type(project.vcs_strategy).__name__
print(f"VCS Strategy: {vcs_name}")

# Access VCS-specific functionality
if hasattr(project.vcs_strategy, 'root'):
    vcs_root = project.vcs_strategy.root
    print(f"VCS root: {vcs_root}")

Complete Project Analysis Example

from reuse.project import Project
from pathlib import Path
import json

def analyze_project(project_path: Path) -> dict:
    """Comprehensive project analysis example."""
    
    # Create project instance
    project = Project.from_directory(project_path, include_submodules=True)
    
    analysis = {
        "root": str(project.root),
        "vcs_strategy": type(project.vcs_strategy).__name__,
        "has_global_licensing": project.global_licensing is not None,
        "license_files": len(project.licenses),
        "files_analyzed": 0,
        "files_with_reuse_info": 0,
        "files_missing_info": []
    }
    
    # Analyze all files
    for file_path in project.all_files():
        analysis["files_analyzed"] += 1
        
        reuse_info = project.reuse_info_of(file_path)
        if any(info.contains_info() for info in reuse_info):
            analysis["files_with_reuse_info"] += 1
        else:
            rel_path = project.relative_from_root(file_path)
            analysis["files_missing_info"].append(str(rel_path))
    
    # Calculate compliance percentage
    if analysis["files_analyzed"] > 0:
        compliance = (analysis["files_with_reuse_info"] / analysis["files_analyzed"]) * 100
        analysis["compliance_percentage"] = round(compliance, 2)
    
    return analysis

# Usage
project_analysis = analyze_project(Path("/path/to/project"))
print(json.dumps(project_analysis, indent=2))

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