Skip to content

Commit

Permalink
Lint everything (#6)
Browse files Browse the repository at this point in the history
* Format everything with `black`

* Make flake8 happy
  • Loading branch information
toastwaffle authored Feb 10, 2025
1 parent cee0461 commit 75a02f6
Show file tree
Hide file tree
Showing 29 changed files with 938 additions and 878 deletions.
9 changes: 5 additions & 4 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# .flake8 - Flake8 configuration
[flake8]
max-line-length = 88
extend-ignore = E203, W503
exclude =
extend-ignore = E203, W503, E501
exclude =
.git,
__pycache__,
build,
dist,
*.egg-info
*.egg-info,
.venv
per-file-ignores =
# F401: imported but unused
__init__.py: F401
__init__.py: F401
2 changes: 1 addition & 1 deletion asciidoc_linter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
AsciiDoc Linter - A Python based linter for AsciiDoc files
"""

__version__ = '0.1.0'
__version__ = "0.1.0"
25 changes: 17 additions & 8 deletions asciidoc_linter/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,48 @@
for rule checking
"""

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


@dataclass
class AsciiDocElement:
"""Base class for AsciiDoc elements"""

line_number: int
content: str



@dataclass
class Header(AsciiDocElement):
"""Represents an AsciiDoc header"""

level: int


@dataclass
class CodeBlock(AsciiDocElement):
"""Represents a code block"""

language: Optional[str]



@dataclass
class Table(AsciiDocElement):
"""Represents a table"""

columns: int



class AsciiDocParser:
"""Parser for AsciiDoc content"""

def parse(self, content: str) -> List[AsciiDocElement]:
"""Parse AsciiDoc content into elements"""
# TODO: Implement actual parsing
elements = []
for line_number, line in enumerate(content.splitlines(), 1):
if line.startswith('='):
level = len(line) - len(line.lstrip('='))
if line.startswith("="):
level = len(line) - len(line.lstrip("="))
elements.append(Header(line_number, line, level))
return elements
return elements
10 changes: 2 additions & 8 deletions asciidoc_linter/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@
"""

# Import only the base classes and types
from .rules.base import (
Severity,
Position,
Finding,
Rule,
RuleRegistry
)
from .rules.base import Severity, Position, Finding, Rule, RuleRegistry

# Only export the base classes and types
__all__ = ['Severity', 'Position', 'Finding', 'Rule', 'RuleRegistry']
__all__ = ["Severity", "Position", "Finding", "Rule", "RuleRegistry"]
8 changes: 1 addition & 7 deletions asciidoc_linter/rules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,4 @@

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

__all__ = [
'Rule',
'Finding',
'Severity',
'Position',
'RuleRegistry'
]
__all__ = ["Rule", "Finding", "Severity", "Position", "RuleRegistry"]
84 changes: 53 additions & 31 deletions asciidoc_linter/rules/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@
from enum import Enum
from dataclasses import dataclass


class Severity(str, Enum):
"""
Severity levels for findings.
Inherits from str to ensure consistent string representation.
All values are lowercase to ensure consistency.
"""

ERROR = "error"
WARNING = "warning"
INFO = "info"

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

def __eq__(self, other: object) -> bool:
"""
Enhanced equality check that handles string comparison.
Expand All @@ -30,17 +32,20 @@ def __eq__(self, other: object) -> bool:
return self.value.lower() == other.lower()
return super().__eq__(other)


@dataclass
class Position:
"""Represents a position in a text file"""

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"""
Expand Down Expand Up @@ -94,13 +99,15 @@ def __post_init__(self):
except ValueError:
self.severity = Severity.WARNING # Default to warning if invalid


class Rule:
"""Base class for all rules"""

id: str = "BASE" # Default ID, 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

def __init__(self):
"""
Initialize the rule and ensure severity is a proper enum value
Expand All @@ -110,105 +117,120 @@ def __init__(self):
self.severity = Severity(self.severity.lower())
except ValueError:
self.severity = Severity.WARNING

@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]:

def check_line(
self, line: str, line_number: int, context: List[str]
) -> List[Finding]:
"""
Check a single line for rule violations.
Args:
line: The current line to check
line_number: The line number in the document (0-based)
context: The complete document as a list of lines
Returns:
List of Finding objects representing rule violations
"""
findings = []

# Get previous and next lines if available
prev_line = context[line_number - 1] if line_number > 0 else None
next_line = context[line_number + 1] if line_number < len(context) - 1 else None

# Check the line content
line_findings = self.check_line_content(line, line_number)
if line_findings:
findings.extend(line_findings)

# Check line context if needed
context_findings = self.check_line_context(line, line_number, prev_line, next_line)
context_findings = self.check_line_context(
line, line_number, prev_line, next_line
)
if context_findings:
findings.extend(context_findings)

return findings

def check_line_content(self, line: str, line_number: int) -> List[Finding]:
"""
Check the content of a single line.
Override this method in concrete rule implementations.
"""
return []

def check_line_context(self, line: str, line_number: int,
prev_line: Optional[str], next_line: Optional[str]) -> List[Finding]:

def check_line_context(
self,
line: str,
line_number: int,
prev_line: Optional[str],
next_line: Optional[str],
) -> List[Finding]:
"""
Check a line in context with its surrounding lines.
Override this method in concrete rule implementations.
"""
return []

def create_finding(self, line_number: int, message: str,
column: Optional[int] = None, context: Optional[Dict[str, Any]] = None) -> Finding:

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


class RuleRegistry:
"""Registry for all available rules"""

_rules: Dict[str, Type[Rule]] = {}

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

@classmethod
def get_rule(cls, rule_name: str) -> Type[Rule]:
"""Get a rule class by name"""
return cls._rules[rule_name]

@classmethod
def get_all_rules(cls) -> List[Type[Rule]]:
"""Get all registered rules"""
return list(cls._rules.values())

@classmethod
def create_all_rules(cls) -> List[Rule]:
"""Create instances of all registered rules"""
return [rule_class() for rule_class in cls.get_all_rules()]
return [rule_class() for rule_class in cls.get_all_rules()]
10 changes: 2 additions & 8 deletions asciidoc_linter/rules/base_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
This module re-exports the base functionality from base.py for backward compatibility.
"""

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

__all__ = ['Severity', 'Position', 'Finding', 'Rule', 'RuleRegistry']
__all__ = ["Severity", "Position", "Finding", "Rule", "RuleRegistry"]
Loading

0 comments on commit 75a02f6

Please sign in to comment.