Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add a environment / config variable to ignore certain certain function patterns #25

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
11 changes: 9 additions & 2 deletions codelimit/__main__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
from pathlib import Path
from typing import List, Annotated
from typing import List, Annotated, Optional

import typer

from codelimit.common.CheckResult import CheckResult
from codelimit.common.Configuration import Configuration
from codelimit.common.Scanner import scan_codebase, is_excluded
from codelimit.common.report.Report import Report
from codelimit.common.report.ReportReader import ReportReader
Expand Down Expand Up @@ -91,8 +92,14 @@ def upload(


@cli.callback()
def main():
def main(
exclude: Annotated[
Optional[list[str]], typer.Option(help="Glob patterns for exclusion")
] = None
):
"""CodeLimit: Your refactoring alarm."""
if exclude:
Configuration.excludes.extend(exclude)


if __name__ == "__main__":
Expand Down
57 changes: 29 additions & 28 deletions codelimit/common/Configuration.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
default_excludes = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
"test",
"tests",
]
class Configuration:
excludes = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
"test",
"tests",
]
15 changes: 11 additions & 4 deletions codelimit/common/Scanner.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fnmatch
import os
from os.path import relpath
from pathlib import Path
Expand All @@ -6,7 +7,7 @@
from halo import Halo

from codelimit.common.Codebase import Codebase
from codelimit.common.Configuration import default_excludes
from codelimit.common.Configuration import Configuration
from codelimit.common.Language import Language
from codelimit.common.Location import Location
from codelimit.common.Measurement import Measurement
Expand Down Expand Up @@ -96,7 +97,13 @@ def scan_file(language: Language, path: str) -> list[Measurement]:


def is_excluded(path: Path):
for part in path.parts[:-1]:
if part in default_excludes:
return True
for exclude in Configuration.excludes:
exclude_parts = exclude.split(os.sep)
if len(exclude_parts) == 1:
for part in path.parts:
if fnmatch.fnmatch(part, exclude):
return True
else:
if fnmatch.fnmatch(str(path), exclude):
return True
return False
48 changes: 46 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,57 @@ Or you can ignore a function by putting a `# nocl` comment on any line of the
header:

```python
def some_function(): # nocl
def some_function(): # nocl
...
```

```python
def some_functions(
some_numbers: list[int]
) -> int: # nocl
) -> int: # nocl
...
```

## Excluding files

Files can be excluded from analysis by using the `--exclude` option.
This option can be used multiple times and takes a [glob pattern](https://en.wikipedia.org/wiki/Glob_(programming)) as a
value, for example:

```shell
codelimit --exclude "*.generated.py" --exclude "docs/*" ...
```

The `--exclude` option extends the default exclusion list.
The default exclusion list is:

```python
[
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
"test",
"tests",
]
```
18 changes: 17 additions & 1 deletion tests/common/test_Scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import tempfile
from pathlib import Path

from codelimit.common.Scanner import scan_codebase
from codelimit.common.Configuration import Configuration
from codelimit.common.Scanner import scan_codebase, is_excluded
from codelimit.common.source_utils import get_location_range


Expand Down Expand Up @@ -68,3 +69,18 @@ def test_skip_hidden_files():
assert result.total_loc() == 2
assert len(result.all_measurements()) == 1
assert result.all_files()[0] == "foo.py"


def test_is_excluded():
assert is_excluded(Path("venv/foo/bar.py"))
assert not is_excluded(Path("foo/bar.py"))

Configuration.excludes = ["output"]

assert is_excluded(Path("output/foo/bar.py"))
assert not is_excluded(Path("venv/foo/bar.py"))
assert not is_excluded(Path("foo/bar.py"))

Configuration.excludes = ["foo/bar/*"]

assert is_excluded(Path("foo/bar/foobar.py"))
Loading