CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-prospector

Prospector is a tool to analyse Python code by aggregating the result of other tools.

Pending
Overview
Eval results
Files

profiles.mddocs/

Profiles

Configuration profile system for managing tool settings, rules, and project-specific configurations. Profiles allow customization of Prospector's behavior for different projects and coding styles.

Capabilities

ProspectorProfile Class

Main configuration profile class that manages tool settings and rules.

class ProspectorProfile:
    pass

Represents a configuration profile with tool settings, enabled/disabled rules, and other preferences.

@staticmethod
def load(name: Union[str, Path], profile_path: list[Path], 
         forced_inherits: Optional[list[str]] = None) -> ProspectorProfile

Loads a profile from the filesystem or built-in profiles.

Parameters:

  • name: Union[str, Path] - Profile name or path to profile file
  • profile_path: list[Path] - List of directories to search for profiles
  • forced_inherits: Optional[list[str]] - Additional profiles to inherit from

Returns:

  • ProspectorProfile - Loaded and configured profile

Raises:

  • ProfileNotFound - If the specified profile cannot be found
  • CannotParseProfile - If the profile file contains invalid YAML

Profile Search Order:

  1. Explicit path if name is a Path
  2. Directories in profile_path list
  3. Built-in profiles directory
  4. Python packages named prospector_profile_{module_name}
def is_tool_enabled(self, tool_name: str) -> Optional[bool]

Checks if a specific tool is enabled in this profile.

Parameters:

  • tool_name: str - Name of the tool to check

Returns:

  • Optional[bool] - True if enabled, False if disabled, None if not specified
def get_disabled_messages(self, tool_name: str) -> list[str]

Gets list of message codes disabled for a specific tool.

Parameters:

  • tool_name: str - Name of the tool

Returns:

  • list[str] - List of disabled message codes
def get_enabled_messages(self, tool_name: str) -> list[str]

Gets list of message codes enabled for a specific tool.

Parameters:

  • tool_name: str - Name of the tool

Returns:

  • list[str] - List of enabled message codes
def list_profiles(self) -> list[str]

Lists all profiles that were loaded (including inherited profiles).

Returns:

  • list[str] - List of profile names in inheritance order

Profile Properties

Profile objects have various properties for accessing configuration:

  • autodetect: bool - Whether to auto-detect libraries and frameworks
  • uses: list[str] - Explicitly specified libraries/frameworks to use
  • ignore_patterns: list[str] - Regex patterns for files to ignore
  • ignore_paths: list[str] - Specific paths to ignore
  • output_format: str - Default output format
  • output_target: list[str] - Default output target files

Auto-Loaded Profiles

AUTO_LOADED_PROFILES: list[Path]

List of profile filenames that Prospector automatically searches for in the working directory.

Auto-loaded Profile Files:

  • .landscape.yml / .landscape.yaml
  • landscape.yml / landscape.yaml
  • .prospector.yml / .prospector.yaml
  • prospector.yml / prospector.yaml
  • prospector/.prospector.yml / prospector/.prospector.yaml
  • prospector/prospector.yml / prospector/prospector.yaml
  • .prospector/.prospector.yml / .prospector/.prospector.yaml
  • .prospector/prospector.yml / .prospector/prospector.yaml

Profile Exceptions

class ProfileNotFound(Exception):
    def __init__(self, name: str, profile_path: list[Path]) -> None

Raised when a requested profile cannot be found.

Properties:

  • name: str - Name of the profile that wasn't found
  • profile_path: list[Path] - Search paths that were checked
class CannotParseProfile(Exception):
    def __init__(self, filepath: Path, parse_error: Any) -> None

Raised when a profile file contains invalid YAML or configuration.

Properties:

  • filepath: Path - Path to the problematic profile file
  • parse_error: Any - The underlying parsing error
def get_parse_message(self) -> str

Gets a human-readable error message describing the parse failure.

Usage Examples

Loading Profiles

from prospector.profiles.profile import ProspectorProfile
from pathlib import Path

# Load default profile
try:
    profile = ProspectorProfile.load("default", [Path("/usr/share/prospector/profiles")])
    print(f"Loaded profile with {len(profile.list_profiles())} inherited profiles")
except Exception as e:
    print(f"Failed to load profile: {e}")

# Load custom profile from specific location
profile_paths = [
    Path(".prospector"),
    Path("/etc/prospector/profiles"),
    Path.home() / ".config/prospector/profiles"
]

try:
    profile = ProspectorProfile.load("myproject", profile_paths)
    print("Loaded custom profile")
except Exception as e:
    print(f"Custom profile not found: {e}")

Checking Tool Configuration

from prospector.profiles.profile import ProspectorProfile
from pathlib import Path

profile = ProspectorProfile.load("default", [Path("/usr/share/prospector/profiles")])

# Check which tools are enabled
tools_to_check = ["pylint", "pyflakes", "mypy", "bandit"]

for tool in tools_to_check:
    enabled = profile.is_tool_enabled(tool)
    if enabled is True:
        print(f"{tool}: enabled")
    elif enabled is False:
        print(f"{tool}: disabled")
    else:
        print(f"{tool}: not specified (use default)")

# Check disabled messages for pylint
disabled = profile.get_disabled_messages("pylint")
if disabled:
    print(f"Pylint disabled messages: {disabled}")

# Check enabled messages for pydocstyle
enabled = profile.get_enabled_messages("pydocstyle")
if enabled:
    print(f"Pydocstyle enabled messages: {enabled}")

Creating Profile Files

# Example .prospector.yaml file
strictness: medium
test-warnings: false
doc-warnings: true
autodetect: true

uses:
  - django
  - celery

ignore-patterns:
  - '(^|/)migrations(/|$)'
  - '\.pb2\.py$'

ignore-paths:
  - docs
  - build
  - venv

output-format: grouped

pylint:
  disable:
    - missing-docstring
    - invalid-name
  options:
    max-line-length: 120

pycodestyle:
  disable:
    - E501  # line too long
  options:
    max-line-length: 120

mypy:
  run: true
  options:
    ignore-missing-imports: true

Working with Profile Inheritance

from prospector.profiles.profile import ProspectorProfile
from pathlib import Path

# Load profile with forced inheritance
profile = ProspectorProfile.load(
    "myproject",
    [Path(".prospector")],
    forced_inherits=["strictness_high", "django"]
)

# See what profiles were loaded
profiles = profile.list_profiles()
print(f"Profile inheritance chain: {' -> '.join(profiles)}")

# Check if specific settings come from inheritance
if profile.autodetect:
    print("Auto-detection is enabled")

libraries = profile.uses
if libraries:
    print(f"Configured for libraries: {libraries}")

Error Handling

from prospector.profiles.profile import ProspectorProfile, ProfileNotFound, CannotParseProfile
from pathlib import Path

def load_profile_safely(name: str, search_paths: list[Path]) -> ProspectorProfile:
    try:
        return ProspectorProfile.load(name, search_paths)
    except ProfileNotFound as e:
        print(f"Profile '{e.name}' not found in paths: {e.profile_path}")
        print("Falling back to default profile")
        return ProspectorProfile.load("default", search_paths)
    except CannotParseProfile as e:
        print(f"Failed to parse profile file {e.filepath}:")
        print(e.get_parse_message())
        raise

# Usage
search_paths = [Path("."), Path("/etc/prospector")]
profile = load_profile_safely("myproject", search_paths)

Auto-Detection of Profiles

from prospector.profiles import AUTO_LOADED_PROFILES
from pathlib import Path
import os

def find_auto_profile(working_dir: Path) -> Optional[Path]:
    """Find automatically loaded profile in working directory"""
    for profile_path in AUTO_LOADED_PROFILES:
        full_path = working_dir / profile_path
        if full_path.exists() and full_path.is_file():
            return full_path
    return None

# Check current directory
current_dir = Path.cwd()
auto_profile = find_auto_profile(current_dir)

if auto_profile:
    print(f"Found auto-loaded profile: {auto_profile}")
    # This profile would be automatically loaded by ProspectorConfig
else:
    print("No auto-loaded profile found")
    print("Checked for these files:")
    for profile_path in AUTO_LOADED_PROFILES:
        print(f"  {profile_path}")

Dynamic Profile Configuration

from prospector.profiles.profile import ProspectorProfile
from prospector.config import ProspectorConfig
from pathlib import Path

def configure_for_project(project_type: str) -> ProspectorConfig:
    """Configure Prospector based on project type"""
    
    # Determine appropriate profiles
    if project_type == "django":
        forced_inherits = ["django", "strictness_medium"]
    elif project_type == "flask":
        forced_inherits = ["flask", "strictness_medium"]
    elif project_type == "library":
        forced_inherits = ["strictness_high", "doc_warnings"]
    else:
        forced_inherits = ["strictness_medium"]
    
    # Create config with custom profile loading
    config = ProspectorConfig()
    
    # Override profile with project-specific settings
    profile_paths = [
        Path(".prospector"),
        Path("/etc/prospector/profiles")
    ]
    
    try:
        profile = ProspectorProfile.load(
            "default",
            profile_paths,
            forced_inherits=forced_inherits
        )
        config.profile = profile
        print(f"Configured for {project_type} project")
    except Exception as e:
        print(f"Failed to configure for {project_type}: {e}")
    
    return config

# Usage
django_config = configure_for_project("django")
library_config = configure_for_project("library")

Profile Validation

from prospector.profiles.profile import ProspectorProfile
from pathlib import Path
import yaml

def validate_profile_file(profile_path: Path) -> bool:
    """Validate a profile file before loading"""
    try:
        # Check if file exists and is readable
        if not profile_path.exists():
            print(f"Profile file does not exist: {profile_path}")
            return False
        
        # Try to parse as YAML
        with open(profile_path, 'r') as f:
            yaml.safe_load(f)
        
        # Try to load as Prospector profile
        ProspectorProfile.load(str(profile_path), [profile_path.parent])
        
        print(f"Profile file is valid: {profile_path}")
        return True
        
    except yaml.YAMLError as e:
        print(f"YAML syntax error in {profile_path}: {e}")
        return False
    except Exception as e:
        print(f"Profile validation failed for {profile_path}: {e}")
        return False

# Validate profile files
profile_files = [
    Path(".prospector.yaml"),
    Path("profiles/myproject.yaml"),
    Path("profiles/strict.yaml")
]

for profile_file in profile_files:
    validate_profile_file(profile_file)

Install with Tessl CLI

npx tessl i tessl/pypi-prospector

docs

analysis-runner.md

configuration.md

exceptions.md

file-finding.md

formatters.md

index.md

messages.md

profiles.md

tools.md

tile.json