Skip to content

Commit

Permalink
Make all the tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
toastwaffle committed Feb 7, 2025
1 parent 79873ba commit e861289
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 309 deletions.
11 changes: 6 additions & 5 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ asciidoc-lint --format json document.adoc

The linter supports three output formats:

* `console` (default): Human-readable output
* `console` (default): Human-readable output with color
* `plain`: Human-readable output without color
* `json`: Machine-readable JSON format
* `html`: HTML report format

Expand Down Expand Up @@ -143,8 +144,8 @@ WARNING: Missing alt text for image: diagram.png (line 80)

=== Current Status

* Test Coverage: 95%
* Test Success Rate: 97.3% (107/110 tests passing)
* Test Coverage: 94%
* Test Success Rate: 100% (127/127 tests passing)
* Known Issues:
** Table content validation needs improvement
** Rules.py requires test coverage
Expand All @@ -155,10 +156,10 @@ WARNING: Missing alt text for image: diagram.png (line 80)
[source,bash]
----
# Run all tests
python run_tests.py
python -m pytest
# Run specific test file
python -m unittest tests/rules/test_heading_rules.py
python -m pytest tests/rules/test_heading_rules.py
# Run tests with coverage
python run_tests_html.py
Expand Down
27 changes: 16 additions & 11 deletions asciidoc_linter/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
import argparse
import sys
from typing import List, Optional
from pathlib import Path
from .linter import AsciiDocLinter
from .reporter import ConsoleReporter, JsonReporter, HtmlReporter
from .reporter import ConsoleReporter, JsonReporter, HtmlReporter, Reporter

def create_parser() -> argparse.ArgumentParser:
"""Create the command line parser"""
Expand All @@ -26,31 +25,37 @@ def create_parser() -> argparse.ArgumentParser:
)
parser.add_argument(
'--format',
choices=['console', 'json', 'html'],
choices=['console', 'plain', 'json', 'html'],
default='console',
help='Output format (default: console)'
)
return parser

def get_reporter(format: str) -> Reporter:
if format == 'json':
return JsonReporter()
if format == 'html':
return HtmlReporter()
if format == 'plain':
return ConsoleReporter(enable_color=False)
if format == 'console':
return ConsoleReporter(enable_color=True)
raise ValueError(f"Unrecognised format {format}")

def main(args: Optional[List[str]] = None) -> int:
"""Main entry point for the linter"""
if args is None:
args = sys.argv[1:]

parser = create_parser()
parsed_args = parser.parse_args(args)

report = AsciiDocLinter().lint(parsed_args.files)

# Set reporter based on format argument
reporter = ConsoleReporter()
if parsed_args.format == 'json':
reporter = JsonReporter()
elif parsed_args.format == 'html':
reporter = HtmlReporter()
print(reporter.format_report(report))
print(get_reporter(parsed_args.format).format_report(report))

return report.exit_code

if __name__ == '__main__':
sys.exit(main())
sys.exit(main())
22 changes: 11 additions & 11 deletions asciidoc_linter/linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Main linter module that processes AsciiDoc files and applies rules
"""

from typing import List, Optional
from typing import List
from pathlib import Path

from .rules.base import Finding, Severity
Expand All @@ -19,11 +19,11 @@
from .rules.whitespace_rules import WhitespaceRule
from .rules.image_rules import ImageAttributesRule
from .parser import AsciiDocParser
from .reporter import LintReport, ConsoleReporter, Reporter
from .reporter import LintReport

class AsciiDocLinter:
"""Main linter class that coordinates parsing and rule checking"""

def __init__(self):
self.parser = AsciiDocParser()
self.rules = [
Expand All @@ -35,23 +35,23 @@ def __init__(self):
WhitespaceRule(),
ImageAttributesRule()
]

def lint(self, file_paths: List[str]) -> LintReport:
"""
Lint content and return formatted output using the current reporter
This is the main entry point used by the CLI
"""
all_findings = []
for file_path in file_paths:
all_findings.extend(self.lint_file(file_path))
return LintReport(all_findings)

def lint_file(self, file_path: Path) -> List[Finding]:
"""Lint a single file and return a report"""
try:
return [
finding.set_file(file_path)
finding.set_file(str(file_path))
for finding in self.lint_string(Path(file_path).read_text())
]
except Exception as e:
Expand All @@ -61,14 +61,14 @@ def lint_file(self, file_path: Path) -> List[Finding]:
severity=Severity.ERROR,
file=str(file_path))
]

def lint_string(self, content: str) -> List[Finding]:
"""Lint a string and return a report"""
document = self.parser.parse(content)
findings = []

for rule in self.rules:
rule_findings = rule.check(document)
findings.extend(rule_findings)
return findings

return findings
82 changes: 49 additions & 33 deletions asciidoc_linter/reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Different output formatters for lint results
"""

from abc import ABC, abstractmethod
from collections import defaultdict
from dataclasses import dataclass
from typing import List, Dict, Optional
Expand Down Expand Up @@ -31,36 +32,47 @@ def __bool__(self):
def __len__(self):
return len(self.findings)

class Reporter:
class Reporter(ABC):
"""Base class for lint report formatters."""

@abstractmethod
def format_report(self, report: LintReport) -> str:
pass

class ConsoleReporter(Reporter):
"""Base class for formatting lint reports"""

def __init__(self, enable_color):
self.enable_color = enable_color

def _green(self, text):
if not self.enable_color:
return text
return f"\033[32m{text}\033[0m"

def _red(self, text):
if not self.enable_color:
return text
return f"\033[31m{text}\033[0m"

def format_report(self, report: LintReport) -> str:
"""Format the report as string"""
if not report:
return "✓ No issues found"
return self._green("✓ No issues found")

output = []
for file, findings in report.grouped_findings().items():
output.append(f"Results for {file}:")
for finding in findings:
output.append(f"{finding.location}: {finding.message}")
output.append("\n")

return "\n".join(output)
if file:
output.append(f"Results for {file}:")
else:
output.append(f"Results without file:")

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:
return "\033[32m✓ No issues found\033[0m"

output = []
for file, findings in report.grouped_findings().items():
output.append(f"Results for {file}:")
for finding in findings:
output.append(f"\033[31m✗\033[0m {finding.location}: {finding.message}")
location = finding.location
if location:
output.append(f"{self._red('✗')} {finding.location}: {finding.message}")
else:
output.append(f"{self._red('✗')} {finding.message}")
output.append("\n")

return "\n".join(output)
Expand All @@ -69,25 +81,29 @@ class JsonReporter(Reporter):
"""Reports findings in JSON format"""

def format_report(self, report: LintReport) -> str:
return json.dumps([
finding.to_json_object()
for finding in report.findings
], indent=2)
return json.dumps({
"findings": [
finding.to_json_object()
for finding in report.findings
],
}, indent=2)

class HtmlReporter(Reporter):
"""Reports findings in HTML format"""

def format_report(self, report: LintReport) -> str:
rows = []
for finding in report.findings:
rows.append(
f'<tr>'
f'<td>{finding.severity}</td>'
f'<td>{finding.rule_id or ""}</td>'
f'<td>{finding.location}</td>'
f'<td>{finding.message}</td>'
f'</tr>'
)
rows.extend([
f'<tr>',
f'<td>{finding.severity}</td>',
f'<td>{finding.rule_id or ""}</td>',
f'<td>{finding.location}</td>',
f'<td>{finding.message}</td>',
f'</tr>',
])

rows = "\n".join(rows)

return f"""<!DOCTYPE html>
<html>
Expand All @@ -111,7 +127,7 @@ def format_report(self, report: LintReport) -> str:
<th>Location</th>
<th>Message</th>
</tr>
{"".join(rows)}
{rows}
</table>
</body>
</html>"""
25 changes: 0 additions & 25 deletions run_tests.py

This file was deleted.

1 change: 0 additions & 1 deletion run_tests.py.meta

This file was deleted.

Loading

0 comments on commit e861289

Please sign in to comment.