Skip to content

Commit

Permalink
feat(rust): version 1.1.0
Browse files Browse the repository at this point in the history
- Update to version 1.1.0
- Let the user pass multiple paths to analyze
- Remove the `--level` option
- Refactor code to not use the old `--level` option
- Update docs
- Update tests
- Add the `requirements.txt` file
  • Loading branch information
rohaquinlop committed Dec 14, 2024
1 parent 3be97b7 commit d13aeb9
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 245 deletions.
23 changes: 18 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "complexipy"
version = "0.5.0"
version = "1.1.0"
edition = "2021"
authors = ["Robin Quintero <[email protected]>"]
license = "MIT"
Expand All @@ -22,5 +22,6 @@ ignore = "0.4.22"
indicatif = "0.17.8"
pyo3 = "0.19.0"
rayon = "1.8.1"
regex = "1.11.1"
rustpython-parser = { git = "https://github.com/RustPython/Parser.git", rev = "9ce55aefdeb35e2f706ce0b02d5a2dfe6295fc57" }
tempfile = "3.10.0"
14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ complexipy path/to/file.py -c 20 # Use the -c option to set the maximum c
complexipy path/to/directory -c 0 # Set the maximum cognitive complexity to 0 to disable the exit with error
complexipy path/to/directory -o # Use the -o option to output the results to a CSV file, default is False
complexipy path/to/directory -d low # Use the -d option to set detail level, default is "normal". If set to "low" will show only files with complexity greater than the maximum complexity
complexipy path/to/directory -l file # Use the -l option to set the level of measurement, default is "function". If set to "file" will measure the complexity of the file and will validate the maximum complexity according to the file complexity.
complexipy path/to/directory -q # Use the -q option to disable the output to the console, default is False.
complexipy path/to/directory -s desc # Use the -s option to set the sort order, default is "asc". If set to "desc" will sort the results in descending order. If set to "asc" will sort the results in ascending order. If set to "name" will sort the results by name.
```
Expand All @@ -85,13 +84,6 @@ complexipy path/to/directory -s desc # Use the -s option to set the sort orde
- `-d` or `--details`: Set the detail level, default is "normal". If set to "low"
will show only files or functions with complexity greater than the maximum
complexity.
- `-l` or `--level` Set the level of measurement, default is "function". If set
to "file" will measure the complexity of the file and will validate the maximum
complexity according to the file complexity. If set to "function" will measure
the complexity of the functions and will validate the maximum complexity
according to the function complexity. This option is useful if you want to set
a maximum complexity according for each file or for each function in the file
(or files).
- `-q` or `--quiet`: Disable the output to the console, default is False.
- `-s` or `--sort`: Set the sort order, default is "asc". If set to "desc" will
sort the results in descending order. If set to "asc" will sort the results in
Expand Down Expand Up @@ -135,7 +127,7 @@ The output of the command
`complexipy path/to/file.py` will be:

```txt
───────────────────────────── 🐙 complexipy 0.4.0 ──────────────────────────────
───────────────────────────── 🐙 complexipy 1.1.0 ──────────────────────────────
Summary
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Path ┃ File ┃ Function ┃ Complexity ┃
Expand All @@ -144,8 +136,8 @@ The output of the command
├───────────────────┼───────────────────┼─────────────┼────────────┤
│ test_decorator.py │ test_decorator.py │ b_decorator │ 1 │
└───────────────────┴───────────────────┴─────────────┴────────────┘
🧠 Total Cognitive Complexity in ./tests/src/test_decorator.py: 1
1 file analyzed in 0.0032 seconds
🧠 Total Cognitive Complexity: 1
1 file analyzed in 0.0092 seconds
────────────────────────── 🎉 Analysis completed! 🎉 ───────────────────────────
```

Expand Down
52 changes: 14 additions & 38 deletions complexipy/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from .types import (
DetailTypes,
Level,
Sort,
)
from .utils import (
output_summary,
has_success_file_level,
has_success_function_level,
has_success_functions,
)
from complexipy import (
rust,
Expand All @@ -16,7 +14,6 @@
from pathlib import (
Path,
)
import re
from rich.console import (
Console,
)
Expand All @@ -26,13 +23,13 @@
root_dir = Path(__file__).resolve().parent.parent
app = typer.Typer(name="complexipy")
console = Console()
version = "0.5.0"
version = "1.1.0"


@app.command()
def main(
path: str = typer.Argument(
help="Path to the directory or file to analyze, it can be a local path or a git repository URL.",
paths: list[str] = typer.Argument(
help="Paths to the directories or files to analyze, it can be a local paths or a git repository URL.",
),
max_complexity: int = typer.Option(
15,
Expand All @@ -49,12 +46,6 @@ def main(
"-d",
help="Specify how detailed should be output, it can be 'low' or 'normal'. Default is 'normal'.",
),
level: Level = typer.Option(
Level.function.value,
"--level",
"-l",
help="Specify the level of measurement, it can be 'function' or 'file'. Default is 'function'.",
),
quiet: bool = typer.Option(
False, "--quiet", "-q", help="Suppress the output to the console."
),
Expand All @@ -65,39 +56,26 @@ def main(
help="Sort the output by complexity, it can be 'asc', 'desc' or 'name'. Default is 'asc'.",
),
):
is_dir = Path(path).is_dir()
_url_pattern = (
r"^(https:\/\/|http:\/\/|www\.|git@)(github|gitlab)\.com(\/[\w.-]+){2,}$"
)
is_url = bool(re.match(_url_pattern, path))
invocation_path = os.getcwd()
file_level = level == Level.file

console.rule(f":octopus: complexipy {version}")
start_time = time.time()
files: list[FileComplexity] = rust.main(path, is_dir, is_url, file_level)
files_complexities: list[FileComplexity] = rust.main(paths)
execution_time = time.time() - start_time
output_csv_path = f"{invocation_path}/complexipy.csv"

if output and file_level:
rust.output_csv_file_level(output_csv_path, files, sort.value)
console.print(f"Results saved in {output_csv_path}")
if output and not file_level:
rust.output_csv_function_level(output_csv_path, files, sort.value)
console.print(f"Results saved in {output_csv_path}")
if output:
rust.output_csv(output_csv_path, files_complexities, sort.value)
console.print(f"Results saved at {output_csv_path}")

# Summary
if not quiet:
has_success = output_summary(
console, file_level, files, max_complexity, details, path, sort
console, max_complexity, details, paths, sort
)
if quiet and not file_level:
has_success = has_success_function_level(files, max_complexity)
if quiet and file_level:
has_success = has_success_file_level(files, max_complexity)
if quiet:
has_success = has_success_functions(files_complexities, max_complexity)

console.print(
f"{len(files)} file{'s' if len(files)> 1 else ''} analyzed in {execution_time:.4f} seconds"
f"{len(files_complexities)} file{'s' if len(files_complexities)> 1 else ''} analyzed in {execution_time:.4f} seconds"
)
console.rule(":tada: Analysis completed! :tada:")

Expand All @@ -107,18 +85,16 @@ def main(

def code_complexity(
code: str,
file_level: bool = True,
) -> CodeComplexity:
return rust.code_complexity(code, file_level)
return rust.code_complexity(code)


def file_complexity(file_path: str, file_level: bool = True) -> FileComplexity:
def file_complexity(file_path: str) -> FileComplexity:
path = Path(file_path)
base_path = path.parent
return rust.file_complexity(
file_path=path.resolve().as_posix(),
base_path=base_path.resolve().as_posix(),
_file_level=file_level,
)


Expand Down
5 changes: 0 additions & 5 deletions complexipy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ class DetailTypes(Enum):
normal = "normal" # Show all files with their complexity


class Level(Enum):
function = "function"
file = "file"


class Sort(Enum):
asc = "asc"
desc = "desc"
Expand Down
73 changes: 13 additions & 60 deletions complexipy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,69 +17,27 @@

def output_summary(
console: Console,
file_level: bool,
files: list[FileComplexity],
max_complexity: int,
details: DetailTypes,
path: str,
sort: Sort,
) -> bool:
if file_level:
table, has_success, total_complexity = create_table_file_level(
files, max_complexity, details, sort
)
else:
table, has_success, total_complexity = create_table_function_level(
files, max_complexity, details, sort
)
table, has_success, total_complexity = create_table(
files, max_complexity, details, sort
)

if details == DetailTypes.low and table.row_count < 1:
console.print(f"No {'file' if file_level else 'function'}{'s' if len(files) > 1 else ''} were found with complexity greater than {max_complexity}.")
console.print(
f"No function{'s' if len(files) > 1 else ''} were found with complexity greater than {max_complexity}."
)
else:
console.print(Align.center(table))
console.print(f":brain: Total Cognitive Complexity in {path}: {total_complexity}")
console.print(f":brain: Total Cognitive Complexity: {total_complexity}")

return has_success


def create_table_file_level(
files: list[FileComplexity], max_complexity: int, details: DetailTypes, sort: Sort
) -> tuple[Table, bool, int]:
has_success = True

table = Table(
title="Summary", show_header=True, header_style="bold magenta", show_lines=True
)
table.add_column("Path")
table.add_column("File")
table.add_column("Complexity")
total_complexity = 0

if sort != Sort.name:
files.sort(key=lambda x: x.complexity)

if sort == Sort.desc:
files.reverse()

for file in files:
total_complexity += file.complexity
if file.complexity > max_complexity and max_complexity != 0:
table.add_row(
f"{file.path}",
f"[green]{file.file_name}[/green]",
f"[red]{file.complexity}[/red]",
)
has_success = False
elif details != DetailTypes.low or max_complexity == 0:
table.add_row(
f"{file.path}",
f"[green]{file.file_name}[/green]",
f"[blue]{file.complexity}[/blue]",
)
return table, has_success, total_complexity


def create_table_function_level(
def create_table(
files: list[FileComplexity],
complexity: int,
details: DetailTypes,
Expand All @@ -90,15 +48,17 @@ def create_table_function_level(
total_complexity = 0

table = Table(
title="Summary", show_header=True, header_style="bold magenta", show_lines=True
title="Summary",
show_header=True,
header_style="bold magenta",
show_lines=True,
)
table.add_column("Path")
table.add_column("File")
table.add_column("Function")
table.add_column("Complexity")

for file in files:
total_complexity += file.complexity
for function in file.functions:
total_complexity += function.complexity
all_functions.append((file.path, file.file_name, function))
Expand Down Expand Up @@ -128,14 +88,7 @@ def create_table_function_level(
return table, has_success, total_complexity


def has_success_file_level(files: list[FileComplexity], max_complexity: int) -> bool:
for file in files:
if file.complexity > max_complexity and max_complexity != 0:
return False
return True


def has_success_function_level(files: list[FileComplexity], complexity: int) -> bool:
def has_success_functions(files: list[FileComplexity], complexity: int) -> bool:
for file in files:
for function in file.functions:
if function.complexity > complexity and complexity != 0:
Expand Down
14 changes: 3 additions & 11 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ complexipy path/to/file.py -c 20 # Use the -c option to set the maximum c
complexipy path/to/directory -c 0 # Set the maximum cognitive complexity to 0 to disable the exit with error
complexipy path/to/directory -o # Use the -o option to output the results to a CSV file, default is False
complexipy path/to/directory -d low # Use the -d option to set detail level, default is "normal". If set to "low" will show only files with complexity greater than the maximum complexity
complexipy path/to/directory -l file # Use the -l option to set the level of measurement, default is "function". If set to "file" will measure the complexity of the file and will validate the maximum complexity according to the file complexity.
complexipy path/to/directory -q # Use the -q option to disable the output to the console, default is False.
complexipy path/to/directory -s desc # Use the -s option to set the sort order, default is "asc". If set to "desc" will sort the results in descending order. If set to "asc" will sort the results in ascending order. If set to "name" will sort the results by name.
```
Expand All @@ -85,13 +84,6 @@ complexipy path/to/directory -s desc # Use the -s option to set the sort orde
- `-d` or `--details`: Set the detail level, default is "normal". If set to "low"
will show only files or functions with complexity greater than the maximum
complexity.
- `-l` or `--level` Set the level of measurement, default is "function". If set
to "file" will measure the complexity of the file and will validate the maximum
complexity according to the file complexity. If set to "function" will measure
the complexity of the functions and will validate the maximum complexity
according to the function complexity. This option is useful if you want to set
a maximum complexity according for each file or for each function in the file
(or files).
- `-q` or `--quiet`: Disable the output to the console, default is False.
- `-s` or `--sort`: Set the sort order, default is "asc". If set to "desc" will
sort the results in descending order. If set to "asc" will sort the results in
Expand Down Expand Up @@ -131,7 +123,7 @@ The cognitive complexity of the file is 1, and the output of the command
`complexipy path/to/file.py` will be:

```txt
───────────────────────────── 🐙 complexipy 0.4.0 ──────────────────────────────
───────────────────────────── 🐙 complexipy 1.1.0 ──────────────────────────────
Summary
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Path ┃ File ┃ Function ┃ Complexity ┃
Expand All @@ -140,8 +132,8 @@ The cognitive complexity of the file is 1, and the output of the command
├───────────────────┼───────────────────┼─────────────┼────────────┤
│ test_decorator.py │ test_decorator.py │ b_decorator │ 1 │
└───────────────────┴───────────────────┴─────────────┴────────────┘
🧠 Total Cognitive Complexity in ./tests/src/test_decorator.py: 1
1 file analyzed in 0.0032 seconds
🧠 Total Cognitive Complexity: 1
1 file analyzed in 0.0092 seconds
────────────────────────── 🎉 Analysis completed! 🎉 ───────────────────────────
```

Expand Down
Loading

0 comments on commit d13aeb9

Please sign in to comment.