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

messages.mddocs/

Messages

Standardized data structures for representing analysis results and source code locations. The Message and Location classes provide a unified format for all analysis tool outputs.

Capabilities

Message Class

Represents a single analysis issue or finding from a static analysis tool.

class Message:
    def __init__(self, source: str, code: str, location: Location, message: str,
                 doc_url: Optional[str] = None, is_fixable: bool = False) -> None

Creates a new message representing an analysis finding.

Parameters:

  • source: str - Name of the tool that generated this message (e.g., "pylint", "pyflakes")
  • code: str - Error/warning code from the tool (e.g., "E501", "unused-import")
  • location: Location - Source code location where the issue was found
  • message: str - Human-readable description of the issue
  • doc_url: Optional[str] - URL to documentation about this issue type
  • is_fixable: bool - Whether this issue can be automatically fixed

Properties:

  • source: str - Tool that generated the message
  • code: str - Error/warning code
  • location: Location - Location of the issue
  • message: str - Human-readable message text
  • doc_url: Optional[str] - Documentation URL
  • is_fixable: bool - Auto-fixable flag

Comparison Methods: Messages can be compared and sorted. Two messages are equal if they have the same location and code. Messages are sorted first by location, then by code.

def __eq__(self, other: object) -> bool
def __lt__(self, other: "Message") -> bool
def __repr__(self) -> str

Location Class

Represents a specific location in source code where an issue was found.

class Location:
    def __init__(self, path: Optional[Union[Path, str]], module: Optional[str],
                 function: Optional[str], line: Optional[int], character: Optional[int],
                 line_end: Optional[int] = None, character_end: Optional[int] = None) -> None

Creates a new location object.

Parameters:

  • path: Optional[Union[Path, str]] - File path (converted to absolute Path)
  • module: Optional[str] - Python module name
  • function: Optional[str] - Function or method name where issue occurs
  • line: Optional[int] - Line number (1-based, None for file-level issues)
  • character: Optional[int] - Character position on the line (0-based)
  • line_end: Optional[int] - End line number for multi-line issues
  • character_end: Optional[int] - End character position for multi-line issues

Properties:

  • path: Optional[Path] - Absolute file path
  • module: Optional[str] - Module name
  • function: Optional[str] - Function name
  • line: Optional[int] - Line number
  • character: Optional[int] - Character position
  • line_end: Optional[int] - End line number
  • character_end: Optional[int] - End character position
def absolute_path(self) -> Optional[Path]

Returns the absolute path to the file.

Returns:

  • Optional[Path] - Absolute path or None if no path was provided
def relative_path(self, root: Optional[Path]) -> Optional[Path]

Returns the path relative to the specified root directory.

Parameters:

  • root: Optional[Path] - Root directory for relative path calculation

Returns:

  • Optional[Path] - Relative path if possible, otherwise absolute path

Comparison Methods: Locations can be compared and sorted. Comparison is done by path first, then line, then character.

def __eq__(self, other: object) -> bool
def __lt__(self, other: "Location") -> bool
def __hash__(self) -> int
def __repr__(self) -> str

Utility Functions

def make_tool_error_message(filepath: Union[Path, str], source: str, code: str, message: str,
                           line: Optional[int] = None, character: Optional[int] = None,
                           module: Optional[str] = None, function: Optional[str] = None) -> Message

Convenience function for creating Message objects for tool errors.

Parameters:

  • filepath: Union[Path, str] - Path to the file
  • source: str - Tool name
  • code: str - Error code
  • message: str - Error message
  • line: Optional[int] - Line number
  • character: Optional[int] - Character position
  • module: Optional[str] - Module name
  • function: Optional[str] - Function name

Returns:

  • Message - New Message object with the specified parameters

Usage Examples

Creating Messages

from pathlib import Path
from prospector.message import Message, Location, make_tool_error_message

# Create a location
location = Location(
    path=Path("src/main.py"),
    module="main",
    function="calculate",
    line=42,
    character=10
)

# Create a message
message = Message(
    source="pylint",
    code="C0103",
    location=location,
    message="Invalid name 'x' for variable",
    doc_url="https://pylint.pycqa.org/en/latest/messages/convention/invalid-name.html",
    is_fixable=False
)

print(f"Issue: {message.message}")
print(f"Location: {message.location}")
print(f"From: {message.source}")

Using Convenience Function

from prospector.message import make_tool_error_message

# Create a message using the convenience function
message = make_tool_error_message(
    filepath="src/utils.py",
    source="pyflakes",
    code="unused-import",
    message="'os' imported but unused",
    line=1,
    character=0,
    module="utils"
)

print(f"{message.source}: {message.message}")

Working with Locations

from pathlib import Path
from prospector.message import Location

# Create location with minimal information
location = Location(
    path="src/main.py",
    module=None,
    function=None, 
    line=100,
    character=15
)

# Get absolute path
abs_path = location.absolute_path()
print(f"Absolute path: {abs_path}")

# Get relative path from project root
project_root = Path("/home/user/myproject")
rel_path = location.relative_path(project_root)
print(f"Relative path: {rel_path}")

# Location for file-level issues
file_location = Location(
    path="setup.py",
    module=None,
    function=None,
    line=None,  # No specific line
    character=None
)

Sorting and Comparing Messages

from prospector.message import Message, Location

# Create multiple messages
messages = [
    Message("pylint", "E501", Location("file2.py", None, None, 10, 0), "Line too long"),
    Message("pylint", "C0103", Location("file1.py", None, None, 5, 0), "Invalid name"),
    Message("pyflakes", "unused", Location("file1.py", None, None, 5, 0), "Unused import"),
    Message("pylint", "E501", Location("file1.py", None, None, 20, 0), "Line too long"),
]

# Sort messages (by location, then by code)
sorted_messages = sorted(messages)

for msg in sorted_messages:
    print(f"{msg.location.path}:{msg.location.line} {msg.source}:{msg.code} {msg.message}")

# Check for duplicates
msg1 = Message("pylint", "E501", Location("test.py", None, None, 10, 0), "Error 1")
msg2 = Message("pylint", "E501", Location("test.py", None, None, 10, 0), "Error 2")

print(f"Are messages equal? {msg1 == msg2}")  # True - same location and code

Multi-line Issues

from prospector.message import Message, Location

# Create location for multi-line issue
location = Location(
    path="src/complex.py",
    module="complex",
    function="long_function",
    line=50,           # Start line
    character=4,       # Start character
    line_end=55,       # End line
    character_end=8    # End character
)

message = Message(
    source="pylint",
    code="R0915",
    location=location,
    message="Too many statements (60/50)"
)

print(f"Issue spans lines {location.line}-{location.line_end}")

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