Skip to content

Commit

Permalink
many updated tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rdmueller committed Dec 20, 2024
1 parent f76c03f commit 2a83d74
Show file tree
Hide file tree
Showing 33 changed files with 2,503 additions and 277 deletions.
23 changes: 23 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# .coveragerc - Coverage configuration file
[run]
source = asciidoc_linter
omit =
*/tests/*
*/site-packages/*
setup.py

[report]
exclude_lines =
pragma: no cover
def __repr__
if self.debug:
raise NotImplementedError
if __name__ == .__main__.:
pass
raise ImportError
except ImportError:
def main\(\):

[html]
directory = htmlcov
title = AsciiDoc Linter Coverage Report
1 change: 1 addition & 0 deletions .coveragerc.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Coverage configuration file
4 changes: 4 additions & 0 deletions asciidoc_linter.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ asciidoc_linter/rules/block_rules.py
asciidoc_linter/rules/heading_rules.py
asciidoc_linter/rules/heading_rules.py.meta
asciidoc_linter/rules/image_rules.py
asciidoc_linter/rules/table_rules.py
asciidoc_linter/rules/whitespace_rules.py
docs/.meta
docs/requirements.adoc
Expand Down Expand Up @@ -95,11 +96,14 @@ tests/__init__.py
tests/__init__.py.meta
tests/test.adoc
tests/test.adoc.meta
tests/test_linter.py
tests/test_reporter.py
tests/rules/.meta
tests/rules/__init__.py
tests/rules/__init__.py.meta
tests/rules/test_block_rules.py
tests/rules/test_heading_rules.py
tests/rules/test_heading_rules.py.meta
tests/rules/test_image_rules.py
tests/rules/test_table_rules.py
tests/rules/test_whitespace_rules.py
16 changes: 15 additions & 1 deletion asciidoc_linter/linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from .rules.whitespace_rules import WhitespaceRule
from .rules.image_rules import ImageAttributesRule
from .parser import AsciiDocParser
from .reporter import LintReport, LintError
from .reporter import LintReport, LintError, ConsoleReporter, Reporter

class AsciiDocLinter:
"""Main linter class that coordinates parsing and rule checking"""
Expand All @@ -34,6 +34,20 @@ def __init__(self):
WhitespaceRule(),
ImageAttributesRule()
]
self.reporter = ConsoleReporter() # Default reporter

def set_reporter(self, reporter: Reporter) -> None:
"""Set the reporter to use for output formatting"""
self.reporter = reporter

def lint(self, content: str, source: Optional[str] = None) -> str:
"""
Lint content and return formatted output using the current reporter
This is the main entry point used by the CLI
"""
report = self.lint_string(content, source)
return self.reporter.format_report(report)

def lint_file(self, file_path: Path) -> LintReport:
"""Lint a single file and return a report"""
Expand Down
2 changes: 1 addition & 1 deletion asciidoc_linter/linter.py.meta
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Main linter module with corrected imports
Main linter module with corrected method names and reporter support
18 changes: 18 additions & 0 deletions asciidoc_linter/reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ def format_report(self, report: LintReport) -> str:

return "\n".join(output)

class ConsoleReporter(Reporter):
"""Reports findings in console format with colors"""

def format_report(self, report: LintReport) -> str:
"""Format the report with ANSI colors"""
if not report.errors:
return "\033[32m✓ No issues found\033[0m"

output = []
for error in report.errors:
location = f"\033[36mline {error.line}\033[0m"
if error.file:
location = f"\033[36m{error.file}:{location}\033[0m"

output.append(f"\033[31m✗\033[0m {location}: {error.message}")

return "\n".join(output)

class JsonReporter(Reporter):
"""Reports findings in JSON format"""

Expand Down
43 changes: 2 additions & 41 deletions asciidoc_linter/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,6 @@
Base classes and interfaces for AsciiDoc linting rules
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List, Optional
from enum import Enum
from .rules.base import Severity, Position, Finding, Rule, RuleRegistry

class Severity(Enum):
"""Severity levels for lint findings"""
ERROR = 'error'
WARNING = 'warning'
INFO = 'info'

@dataclass
class Position:
"""Position in a file"""
line: int
column: Optional[int] = None

@dataclass
class Finding:
"""A lint finding"""
rule_id: str
message: str
severity: Severity
position: Position
context: Optional[str] = None

class Rule(ABC):
"""Base class for all linting rules"""

def __init__(self):
self.id = self.__class__.__name__

@abstractmethod
def check(self, content: str) -> List[Finding]:
"""Check content and return findings"""
pass

@property
@abstractmethod
def description(self) -> str:
"""Return a description of what this rule checks"""
pass
__all__ = ['Severity', 'Position', 'Finding', 'Rule', 'RuleRegistry']
3 changes: 2 additions & 1 deletion asciidoc_linter/rules/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# __init__.py - Rules package initialization

from .base import Rule, Finding, Severity, Position
from .base import Rule, Finding, Severity, Position, RuleRegistry
from .heading_rules import HeadingHierarchyRule, HeadingFormatRule
from .block_rules import UnterminatedBlockRule, BlockSpacingRule
from .whitespace_rules import WhitespaceRule
Expand All @@ -11,6 +11,7 @@
'Finding',
'Severity',
'Position',
'RuleRegistry',
'HeadingHierarchyRule',
'HeadingFormatRule',
'UnterminatedBlockRule',
Expand Down
2 changes: 1 addition & 1 deletion asciidoc_linter/rules/__init__.py.meta
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Rules package initialization with Position class
Rules package initialization
77 changes: 51 additions & 26 deletions asciidoc_linter/rules/base.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,75 @@
# base.py - Base functionality for rules
"""
Base functionality and registry for AsciiDoc linting rules
Base functionality and registry for AsciiDoc linting rules.
This module provides the core classes and functionality for the rule system.
"""

from typing import Type, Dict, List, Optional
from typing import Type, Dict, List, Optional, Any
from enum import Enum
from dataclasses import dataclass

class Severity(Enum):
"""Severity levels for findings"""
INFO = "INFO"
WARNING = "WARNING"
ERROR = "ERROR"
WARNING = "WARNING"
INFO = "INFO"

def __str__(self) -> str:
return self.value

@dataclass
class Position:
"""Represents a position in a text file"""
def __init__(self, line: int, column: Optional[int] = None):
self.line = line
self.column = column

def __str__(self):
line: int
column: Optional[int] = None

def __str__(self) -> str:
if self.column is not None:
return f"line {self.line}, column {self.column}"
return f"line {self.line}"

@dataclass
class Finding:
"""Represents a rule violation finding"""
def __init__(self, rule_id: str, position: Position, message: str,
severity: Severity, context: Optional[str] = None):
self.rule_id = rule_id
self.position = position
self.message = message
self.severity = severity
self.context = context

message: str
severity: Severity
position: Position
rule_id: Optional[str] = None
context: Optional[Dict[str, Any]] = None

@property
def line_number(self) -> int:
"""Backward compatibility for line number access"""
return self.position.line

class Rule:
"""Base class for all rules"""
id: str = ""
name: str = ""
description: str = ""
severity: Severity = Severity.WARNING

id: str = "" # Should be overridden by subclasses
name: str = "" # Should be overridden by subclasses
description: str = "" # Should be overridden by subclasses
severity: Severity = Severity.WARNING # Default severity

@property
def rule_id(self) -> str:
"""
Returns the rule ID. This is a compatibility property that returns
the same value as the id attribute.
"""
return self.id

def check(self, content: str) -> List[Finding]:
"""
Check the content for rule violations.
Must be implemented by concrete rule classes.
Args:
content: The content to check
Returns:
List of findings
"""
raise NotImplementedError("Rule must implement check method")

def check_line(self, line: str, line_number: int, context: List[str]) -> List[Finding]:
"""
Check a single line for rule violations.
Expand Down Expand Up @@ -91,13 +116,13 @@ def check_line_context(self, line: str, line_number: int,
return []

def create_finding(self, line_number: int, message: str,
column: Optional[int] = None, context: Optional[str] = None) -> Finding:
column: Optional[int] = None, context: Optional[Dict[str, Any]] = None) -> Finding:
"""Helper method to create a Finding object"""
return Finding(
rule_id=self.id,
position=Position(line_number, column),
message=message,
severity=self.severity,
position=Position(line=line_number, column=column),
rule_id=self.rule_id,
context=context
)

Expand All @@ -107,7 +132,7 @@ class RuleRegistry:
_rules: Dict[str, Type[Rule]] = {}

@classmethod
def register_rule(cls, rule_class: Type[Rule]):
def register_rule(cls, rule_class: Type[Rule]) -> None:
"""Register a new rule class"""
cls._rules[rule_class.__name__] = rule_class

Expand Down
2 changes: 1 addition & 1 deletion asciidoc_linter/rules/base.py.meta
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Updated base.py with check_line implementation
Updated base functionality for rules with standardized attributes and severity values
53 changes: 14 additions & 39 deletions asciidoc_linter/rules/base_rules.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
# base_rules.py - Contains base classes for the rule system

from enum import Enum
from dataclasses import dataclass
from typing import List, Optional, Dict, Any

class Severity(Enum):
ERROR = "error"
WARNING = "warning"
INFO = "info"

@dataclass
class Position:
line: int
column: Optional[int] = None

@dataclass
class Finding:
message: str
severity: Severity
position: Position
rule_id: Optional[str] = None
context: Optional[Dict[str, Any]] = None

class Rule:
"""Base class for all rules"""
rule_id: str = "BASE" # Should be overridden by subclasses

def check(self, content: str) -> List[Finding]:
"""
Check the content for rule violations
Args:
content: The content to check
Returns:
List of findings
"""
raise NotImplementedError("Rule must implement check method")
# base_rules.py - Import module for base functionality
"""
This module re-exports the base functionality from base.py for backward compatibility.
"""

from .base import (
Severity,
Position,
Finding,
Rule,
RuleRegistry
)

__all__ = ['Severity', 'Position', 'Finding', 'Rule', 'RuleRegistry']
2 changes: 1 addition & 1 deletion asciidoc_linter/rules/base_rules.py.meta
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Base classes for all rules
Import module for base functionality
Loading

0 comments on commit 2a83d74

Please sign in to comment.