Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ jobs:
steps:
- name: 'Checkout sources'
uses: actions/checkout@v3

- name: 'Set up Python'
uses: actions/setup-python@v4
with:
python-version: 3.12

- name: 'Set up Poetry'
uses: snok/install-poetry@v1

- name: 'Install dependencies'
run: poetry install --no-interaction --no-root

- name: 'Checkout pl-snakebattle'
run: git clone https://github.com/getcodelimit/pl-battlesnake.git

- name: 'Run codelimit'
run: poetry run codelimit scan pl-battlesnake
52 changes: 27 additions & 25 deletions codelimit/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,33 @@ def list_commands(self, ctx: Context):

@cli.command(help="Check file(s)")
def check(
paths: Annotated[List[Path], typer.Argument(exists=True)],
quiet: Annotated[
bool, typer.Option("--quiet", help="No output when successful")
] = False,
paths: Annotated[List[Path], typer.Argument(exists=True)],
quiet: Annotated[
bool, typer.Option("--quiet", help="No output when successful")
] = False,
):
check_command(paths, quiet)


@cli.command(help="Scan a codebase")
def scan(
path: Annotated[
Path, typer.Argument(exists=True, file_okay=False, help="Codebase root")
] = Path(".")
path: Annotated[
Path, typer.Argument(exists=True, file_okay=False, help="Codebase root")
] = Path(".")
):
scan_command(path)


@cli.command(help="Show report for codebase")
def report(
path: Annotated[
Path, typer.Argument(exists=True, file_okay=False, help="Codebase root")
] = Path("."),
full: Annotated[bool, typer.Option("--full", help="Show full report")] = False,
totals: Annotated[bool, typer.Option("--totals", help="Only show totals")] = False,
fmt: Annotated[ReportFormat, typer.Option("--format", help="Output format")] = ReportFormat.text
path: Annotated[
Path, typer.Argument(exists=True, file_okay=False, help="Codebase root")
] = Path("."),
full: Annotated[bool, typer.Option("--full", help="Show full report")] = False,
totals: Annotated[bool, typer.Option("--totals", help="Only show totals")] = False,
fmt: Annotated[
ReportFormat, typer.Option("--format", help="Output format")
] = ReportFormat.text,
):
report_command(path, full, totals, fmt)

Expand All @@ -62,18 +64,18 @@ def _version_callback(show: bool):

@cli.callback()
def main(
verbose: Annotated[
Optional[bool], typer.Option("--verbose", "-v", help="Verbose output")
] = False,
exclude: Annotated[
Optional[list[str]], typer.Option(help="Glob patterns for exclusion")
] = None,
version: Annotated[
Optional[bool],
typer.Option(
"--version", "-V", help="Show version", callback=_version_callback
),
] = None,
verbose: Annotated[
Optional[bool], typer.Option("--verbose", "-v", help="Verbose output")
] = False,
exclude: Annotated[
Optional[list[str]], typer.Option(help="Glob patterns for exclusion")
] = None,
version: Annotated[
Optional[bool],
typer.Option(
"--version", "-V", help="Show version", callback=_version_callback
),
] = None,
):
"""CodeLimit: Your refactoring alarm."""
if verbose:
Expand Down
51 changes: 27 additions & 24 deletions codelimit/commands/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@

from codelimit.common.ScanResultTable import ScanResultTable
from codelimit.common.ScanTotals import ScanTotals
from codelimit.common.report import ReportUnit
from codelimit.common.report.Report import Report
from codelimit.common.report.ReportUnit import ReportUnit
from codelimit.common.utils import format_measurement
from codelimit.utils import read_cached_report

REPORT_LENGTH = 10


class ReportFormat(str, Enum):
text = 'text'
markdown = 'markdown'
text = "text"
markdown = "markdown"


def report_command(path: Path, full: bool, totals: bool, fmt: ReportFormat):
Expand All @@ -38,25 +38,28 @@ def _report_totals_text(scan_totals: ScanTotals):


def _report_totals_markdown(st: ScanTotals) -> str:
result = ''
result += '| **Language** | **Files** | **Lines of Code** | **Functions** | ⚠ | ✖ |\n'
result += '| --- | ---: | ---: | ---: | ---: | ---: |\n'
result = ""
result += (
"| **Language** | **Files** | **Lines of Code** | **Functions** | ⚠ | ✖ |\n"
)
result += "| --- | ---: | ---: | ---: | ---: | ---: |\n"
for lt in st.languages_totals():
result += (
f'| {lt.language} | '
f'{lt.files} | '
f'{lt.loc} | '
f'{lt.functions} | '
f'{lt.hard_to_maintain} | '
f'{lt.unmaintainable} |\n'
f"| {lt.language} | "
f"{lt.files} | "
f"{lt.loc} | "
f"{lt.functions} | "
f"{lt.hard_to_maintain} | "
f"{lt.unmaintainable} |\n"
)
result += (
f'| | '
f'**{st.total_files()}** | '
f'**{st.total_loc()}** | '
f'**{st.total_functions()}** | '
f'**{st.total_hard_to_maintain()}** | '
f'**{st.total_unmaintainable()}** |')
f"| | "
f"**{st.total_files()}** | "
f"**{st.total_loc()}** | "
f"**{st.total_functions()}** | "
f"**{st.total_hard_to_maintain()}** | "
f"**{st.total_unmaintainable()}** |"
)
return result


Expand Down Expand Up @@ -109,14 +112,14 @@ def _print_functions_text(root, units, report_units, full):
)


def _print_functions_markdown(root: str | None, report_units: list[ReportUnit]) -> str:
result = ''
result += '| **File** | **Line** | **Column** | **Length** | **Function** |\n'
result += '| --- | ---: | ---: | ---: | --- |\n'
def _print_functions_markdown(root: Path | None, report_units: list[ReportUnit]) -> str:
result = ""
result += "| **File** | **Line** | **Column** | **Length** | **Function** |\n"
result += "| --- | ---: | ---: | ---: | --- |\n"
for unit in report_units:
file_path = unit.file if root is None else root.joinpath(unit.file)
result += (
f'| {str(file_path)} | {unit.measurement.start.line} | {unit.measurement.start.column} | '
f'{unit.measurement.value} | {unit.measurement.unit_name} |\n'
f"| {str(file_path)} | {unit.measurement.start.line} | {unit.measurement.start.column} | "
f"{unit.measurement.value} | {unit.measurement.unit_name} |\n"
)
return result
8 changes: 6 additions & 2 deletions codelimit/common/ScanTotals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@


class ScanTotals:
def __init__(self, language_totals: dict[str, LanguageTotals] | None = None) -> None:
self._languages_totals: dict[str, LanguageTotals] = language_totals if language_totals else {}
def __init__(
self, language_totals: dict[str, LanguageTotals] | None = None
) -> None:
self._languages_totals: dict[str, LanguageTotals] = (
language_totals if language_totals else {}
)

def add(self, entry: SourceFileEntry):
if entry.language not in self._languages_totals:
Expand Down
2 changes: 1 addition & 1 deletion codelimit/common/report/Report.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Report:
VERSION = version

def __init__(self, codebase: Codebase):
self.version = self.VERSION
self.version: str | None = self.VERSION
self.uuid = str(uuid4())
self.codebase = codebase

Expand Down
6 changes: 4 additions & 2 deletions codelimit/common/report/ReportWriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ def _collection(self, items: list):
def _codebase_to_json(self):
json = ""
json += self._open('"codebase": {')
json += self._collection([self._totals_to_json(), self._tree_to_json(), self._measurements_to_json()])
json += self._collection(
[self._totals_to_json(), self._tree_to_json(), self._measurements_to_json()]
)
json += self._close("}")
return json

Expand All @@ -75,7 +77,7 @@ def _totals_item_to_json(self, name: str, language_totals: LanguageTotals) -> st
self._totals_lines_of_code_to_json(language_totals),
self._totals_functions_to_json(language_totals),
self._totals_hard_to_maintain_to_json(language_totals),
self._totals_unmaintainable_to_json(language_totals)
self._totals_unmaintainable_to_json(language_totals),
]
)
json += self._close("}")
Expand Down
32 changes: 18 additions & 14 deletions tests/commands/test_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,28 @@ def test_report_totals_markdown():
python_totals.functions = 3
python_totals.hard_to_maintain = 4
python_totals.unmaintainable = 5
st = ScanTotals(
{
"Python": python_totals
}
)
st = ScanTotals({"Python": python_totals})
result = _report_totals_markdown(st)
assert result == (
'| **Language** | **Files** | **Lines of Code** | **Functions** | ⚠ | ✖ |\n'
'| --- | ---: | ---: | ---: | ---: | ---: |\n'
'| Python | 1 | 2 | 3 | 4 | 5 |\n'
'| | **1** | **2** | **3** | **4** | **5** |'
"| **Language** | **Files** | **Lines of Code** | **Functions** | ⚠ | ✖ |\n"
"| --- | ---: | ---: | ---: | ---: | ---: |\n"
"| Python | 1 | 2 | 3 | 4 | 5 |\n"
"| | **1** | **2** | **3** | **4** | **5** |"
)


def test_print_functions_markdown():
result = _print_functions_markdown(None, [ReportUnit('foo.py', Measurement('bar()', Location(1, 1), Location(30, 1), 30))])
result = _print_functions_markdown(
None,
[
ReportUnit(
"foo.py", Measurement("bar()", Location(1, 1), Location(30, 1), 30)
)
],
)

assert result == (
'| **File** | **Line** | **Column** | **Length** | **Function** |\n'
'| --- | ---: | ---: | ---: | --- |\n'
'| foo.py | 1 | 1 | 30 | bar() |\n'
)
"| **File** | **Line** | **Column** | **Length** | **Function** |\n"
"| --- | ---: | ---: | ---: | --- |\n"
"| foo.py | 1 | 1 | 30 | bar() |\n"
)
30 changes: 15 additions & 15 deletions tests/common/test_Codebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ def test_codebase_entry_single_file():
writer = ReportWriter(report, False)

assert (
writer.to_json()
== f'{{"version": "{report.version}", "uuid": "{report.uuid}", '
'"root": "/", "codebase": {"totals": {"Python": {"files": 1, "lines_of_code": '
'20, "functions": 0, "hard_to_maintain": 0, "unmaintainable": 0}}, "tree": '
'{"./": {"entries": ["foo.py"], "profile": [0, 0, 0, 0]}}, "files": '
'{"foo.py": {"checksum": "abcd1234", "language": "Python", "loc": 20, '
'"profile": [0, 0, 0, 0], "measurements": []}}}}'
writer.to_json()
== f'{{"version": "{report.version}", "uuid": "{report.uuid}", '
'"root": "/", "codebase": {"totals": {"Python": {"files": 1, "lines_of_code": '
'20, "functions": 0, "hard_to_maintain": 0, "unmaintainable": 0}}, "tree": '
'{"./": {"entries": ["foo.py"], "profile": [0, 0, 0, 0]}}, "files": '
'{"foo.py": {"checksum": "abcd1234", "language": "Python", "loc": 20, '
'"profile": [0, 0, 0, 0], "measurements": []}}}}'
)


Expand All @@ -38,14 +38,14 @@ def test_codebase_entry_single_folder_single_file():
writer = ReportWriter(report, False)

assert (
writer.to_json()
== f'{{"version": "{report.version}", "uuid": "{report.uuid}", '
'"root": "/", "codebase": {"totals": {"Python": {"files": 1, "lines_of_code": '
'20, "functions": 0, "hard_to_maintain": 0, "unmaintainable": 0}}, "tree": '
'{"./": {"entries": ["foo/"], "profile": [0, 0, 0, 0]}, "foo/": {"entries": '
'["bar.py"], "profile": [0, 0, 0, 0]}}, "files": {"foo/bar.py": {"checksum": '
'"abcd1234", "language": "Python", "loc": 20, "profile": [0, 0, 0, 0], '
'"measurements": []}}}}'
writer.to_json()
== f'{{"version": "{report.version}", "uuid": "{report.uuid}", '
'"root": "/", "codebase": {"totals": {"Python": {"files": 1, "lines_of_code": '
'20, "functions": 0, "hard_to_maintain": 0, "unmaintainable": 0}}, "tree": '
'{"./": {"entries": ["foo/"], "profile": [0, 0, 0, 0]}, "foo/": {"entries": '
'["bar.py"], "profile": [0, 0, 0, 0]}}, "files": {"foo/bar.py": {"checksum": '
'"abcd1234", "language": "Python", "loc": 20, "profile": [0, 0, 0, 0], '
'"measurements": []}}}}'
)


Expand Down
4 changes: 2 additions & 2 deletions tests/common/test_Measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ def test_to_json():
expected += ' "functions": 1,\n'
expected += ' "hard_to_maintain": 0,\n'
expected += ' "unmaintainable": 0\n'
expected += ' }\n'
expected += ' },\n'
expected += " }\n"
expected += " },\n"
expected += ' "tree": {\n'
expected += ' "./": {\n'
expected += ' "entries": [\n'
Expand Down
2 changes: 1 addition & 1 deletion tests/common/test_ReportReader.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_single_file():
assert result.uuid == report.uuid

assert len(result.codebase.totals) == 1
assert result.codebase.totals['Python'].loc == 20
assert result.codebase.totals["Python"].loc == 20

result_entries = result.codebase.tree["./"].entries
result_measurements = result.codebase.files
Expand Down