Skip to content

Commit

Permalink
first iteration of codacy-ruff (#1)
Browse files Browse the repository at this point in the history
* First version of Codacy-Ruff
* Created Doc generator
* Improved the wrapper to allow configuration files
* Created multiple-tests
  • Loading branch information
DMarinhoCodacy authored Feb 26, 2025
1 parent 0d386dd commit 815a363
Showing 752 changed files with 25,734 additions and 5 deletions.
39 changes: 39 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
version: 2.1

orbs:
codacy: codacy/base@12.1.4
codacy_plugins_test: codacy/plugins-test@2.0.11

workflows:
version: 2
compile_test_deploy:
jobs:
- codacy/checkout_and_version
- codacy/shell:
name: publish_docker_local
cmd: |
docker build -t $CIRCLE_PROJECT_REPONAME:latest .
docker save --output docker-image.tar $CIRCLE_PROJECT_REPONAME:latest
persist_to_workspace: true
requires:
- codacy/checkout_and_version
- codacy_plugins_test/run:
name: plugins_test
run_multiple_tests: true
run_json_tests: false
run_pattern_tests: false
requires:
- publish_docker_local
- codacy/publish_docker:
context: CodacyDocker
requires:
- publish_docker_local
filters:
branches:
only:
- master
- codacy/tag_version:
name: tag_version
context: CodacyAWS
requires:
- codacy/publish_docker
7 changes: 7 additions & 0 deletions .codacyrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tools": [
{
"name": "ruff"
}
]
}
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @codacy/macgyvers
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.ruff_cache/
22 changes: 22 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM python:3.13-alpine3.21

COPY requirements.txt requirements.txt

RUN apk add --no-cache --update bash && \
pip3 install --no-cache-dir -r requirements.txt

COPY src/codacy_ruff.py codacy_ruff.py

COPY /docs /docs

RUN adduser -u 2004 -D docker

RUN chown -R docker:docker /docs /home/docker

RUN chown -R docker:docker /home/docker

USER docker

ENTRYPOINT [ "python" ]

CMD [ "codacy_ruff.py" ]
1,398 changes: 1,398 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

61 changes: 56 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,59 @@
# codacy-public-template
# Codacy Ruff

Template repository for new public repositories.
Co-authored by @valeriupredoi

## GitHub actions
This is the docker engine we use at Codacy to have [Ruff](https://docs.astral.sh/ruff/) support.
You can also create a docker to integrate the tool and language of your choice!
See the [codacy-engine-scala-seed](https://github.com/codacy/codacy-engine-scala-seed) repository for more information.

This repository has the common GitHub actions that we want to have accross all of our public repositories.
They should be kept at `.github/workflows`
## Python compatibility
Ruff is compatible with Python 3.13

## Usage

You can create the docker by doing:

```bash
docker build --no-cache -t codacy-ruff:latest .
```

The docker is ran with the following command:

```bash
docker run -it -v $srcDir:/src codacy-ruff:latest
```

## Generate Docs

1. Update the version in `requirements.txt`

2. Run the DocGenerator to update all the patterns/descriptions and the patterns.xml (from all-patterns test)

```bash
python<version> src/doc_generator.py
```

## Test

We use the [codacy-plugins-test](https://github.com/codacy/codacy-plugins-test) to test our external tools integration.
You can follow the instructions there to make sure your tool is working as expected.

## What is Codacy?

[Codacy](https://www.codacy.com/) is an Automated Code Review Tool that monitors your technical debt, helps you improve your code quality, teaches best practices to your developers, and helps you save time in Code Reviews.

### Among Codacy’s features:

- Identify new Static Analysis issues
- Commit and Pull Request Analysis with GitHub, BitBucket/Stash, GitLab (and also direct git repositories)
- Auto-comments on Commits and Pull Requests
- Integrations with Slack, HipChat, Jira, YouTrack
- Track issues in Code Style, Security, Error Proneness, Performance, Unused Code and other categories

Codacy also helps keep track of Code Coverage, Code Duplication, and Code Complexity.

Codacy supports PHP, Python, Ruby, Java, JavaScript, and Scala, among others.

### Free for Open Source

Codacy is free for Open Source projects.
30 changes: 30 additions & 0 deletions docs/descriptions/A001_builtin-variable-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# builtin-variable-shadowing (A001)
Derived from the flake8-builtins linter.
## What it does
Checks for variable (and function) assignments that use the same names
as builtins.
## Why is this bad?
Reusing a builtin name for the name of a variable increases the
difficulty of reading and maintaining the code, and can cause
non-obvious errors, as readers may mistake the variable for the
builtin and vice versa.
Builtins can be marked as exceptions to this rule via the
lint.flake8-builtins.builtins-ignorelist configuration option.
## Example
```
def find_max(list_of_lists):
max = 0
for flat_list in list_of_lists:
for value in flat_list:
max = max(max, value) # TypeError: 'int' object is not callable
return max
```
## Use instead:
```
def find_max(list_of_lists):
result = 0
for flat_list in list_of_lists:
for value in flat_list:
result = max(result, value)
return result
```
31 changes: 31 additions & 0 deletions docs/descriptions/A002_builtin-argument-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# builtin-argument-shadowing (A002)
Derived from the flake8-builtins linter.
## What it does
Checks for function arguments that use the same names as builtins.
## Why is this bad?
Reusing a builtin name for the name of an argument increases the
difficulty of reading and maintaining the code, and can cause
non-obvious errors, as readers may mistake the argument for the
builtin and vice versa.
Builtins can be marked as exceptions to this rule via the
lint.flake8-builtins.builtins-ignorelist configuration option.
## Example
```
def remove_duplicates(list, list2):
result = set()
for value in list:
result.add(value)
for value in list2:
result.add(value)
return list(result) # TypeError: 'list' object is not callable
```
## Use instead:
```
def remove_duplicates(list1, list2):
result = set()
for value in list1:
result.add(value)
for value in list2:
result.add(value)
return list(result)
```
37 changes: 37 additions & 0 deletions docs/descriptions/A003_builtin-attribute-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# builtin-attribute-shadowing (A003)
Derived from the flake8-builtins linter.
## What it does
Checks for class attributes and methods that use the same names as
Python builtins.
## Why is this bad?
Reusing a builtin name for the name of an attribute increases the
difficulty of reading and maintaining the code, and can cause
non-obvious errors, as readers may mistake the attribute for the
builtin and vice versa.
Since methods and class attributes typically cannot be referenced directly
from outside the class scope, this rule only applies to those methods
and attributes that both shadow a builtin and are referenced from within
the class scope, as in the following example, where the list[int] return
type annotation resolves to the list method, rather than the builtin:
class Class:
@staticmethod
def list() -> None:
pass
@staticmethod
def repeat(value: int, times: int) -> list[int]:
return [value] * times
Builtins can be marked as exceptions to this rule via the
lint.flake8-builtins.builtins-ignorelist configuration option, or
converted to the appropriate dunder method. Methods decorated with
@typing.override or @typing_extensions.override are also
ignored.
## Example
```
class Class:
@staticmethod
def list() -> None:
pass
@staticmethod
def repeat(value: int, times: int) -> list[int]:
return [value] * times
```
23 changes: 23 additions & 0 deletions docs/descriptions/A004_builtin-import-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# builtin-import-shadowing (A004)
Derived from the flake8-builtins linter.
## What it does
Checks for imports that use the same names as builtins.
## Why is this bad?
Reusing a builtin for the name of an import increases the difficulty
of reading and maintaining the code, and can cause non-obvious errors,
as readers may mistake the variable for the builtin and vice versa.
Builtins can be marked as exceptions to this rule via the
lint.flake8-builtins.builtins-ignorelist configuration option.
## Example
```
from rich import print
print("Some message")
```
## Use instead:
```
from rich import print as rich_print
rich_print("Some message")
or:
import rich
rich.print("Some message")
```
33 changes: 33 additions & 0 deletions docs/descriptions/A005_stdlib-module-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# stdlib-module-shadowing (A005)
Derived from the flake8-builtins linter.
## What it does
Checks for modules that use the same names as Python standard-library
modules.
## Why is this bad?
Reusing a standard-library module name for the name of a module increases
the difficulty of reading and maintaining the code, and can cause
non-obvious errors. Readers may mistake the first-party module for the
standard-library module and vice versa.
Standard-library modules can be marked as exceptions to this rule via the
lint.flake8-builtins.builtins-allowed-modules configuration option.
By default, only the last component of the module name is considered, so logging.py,
utils/logging.py, and utils/logging/__init__.py would all clash with the builtin logging
module. With the lint.flake8-builtins.builtins-strict-checking option set to false, the
module path is considered, so only a top-level logging.py or logging/__init__.py will
trigger the rule and utils/logging.py, for example, would not. In preview mode, the default
value of lint.flake8-builtins.builtins-strict-checking is false rather than true in
stable mode.
This rule is not applied to stub files, as the name of a stub module is out
of the control of the author of the stub file. Instead, a stub should aim to
faithfully emulate the runtime module it is stubbing.
As of Python 3.13, errors from modules that use the same name as
standard-library modules now display a custom message.
## Example
```
$ touch random.py
$ python3 -c 'from random import choice'
Traceback (most recent call last):
File "<string>", line 1, in <module>
from random import choice
ImportError: cannot import name 'choice' from 'random' (consider renaming '/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
```
12 changes: 12 additions & 0 deletions docs/descriptions/A006_builtin-lambda-argument-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# builtin-lambda-argument-shadowing (A006)
Derived from the flake8-builtins linter.
## What it does
Checks for lambda arguments that use the same names as Python builtins.
## Why is this bad?
Reusing a builtin name for the name of a lambda argument increases the
difficulty of reading and maintaining the code and can cause
non-obvious errors. Readers may mistake the variable for the
builtin, and vice versa.
Builtins can be marked as exceptions to this rule via the
lint.flake8-builtins.builtins-ignorelist configuration option.
```
19 changes: 19 additions & 0 deletions docs/descriptions/AIR001_airflow-variable-name-task-id-mismatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# airflow-variable-name-task-id-mismatch (AIR001)
Derived from the Airflow linter.
## What it does
Checks that the task variable name matches the task_id value for
Airflow Operators.
## Why is this bad?
When initializing an Airflow Operator, for consistency, the variable
name should match the task_id value. This makes it easier to
follow the flow of the DAG.
## Example
```
from airflow.operators import PythonOperator
incorrect_name = PythonOperator(task_id="my_task")
```
## Use instead:
```
from airflow.operators import PythonOperator
my_task = PythonOperator(task_id="my_task")
```
16 changes: 16 additions & 0 deletions docs/descriptions/ANN001_missing-type-function-argument.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# missing-type-function-argument (ANN001)
Derived from the flake8-annotations linter.
## What it does
Checks that function arguments have type annotations.
## Why is this bad?
Type annotations are a good way to document the types of function arguments. They also
help catch bugs, when used alongside a type checker, by ensuring that the types of
any provided arguments match expectation.
## Example
```
def foo(x): ...
```
## Use instead:
```
def foo(x: int): ...
```
16 changes: 16 additions & 0 deletions docs/descriptions/ANN002_missing-type-args.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# missing-type-args (ANN002)
Derived from the flake8-annotations linter.
## What it does
Checks that function *args arguments have type annotations.
## Why is this bad?
Type annotations are a good way to document the types of function arguments. They also
help catch bugs, when used alongside a type checker, by ensuring that the types of
any provided arguments match expectation.
## Example
```
def foo(*args): ...
```
## Use instead:
```
def foo(*args: int): ...
```
16 changes: 16 additions & 0 deletions docs/descriptions/ANN003_missing-type-kwargs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# missing-type-kwargs (ANN003)
Derived from the flake8-annotations linter.
## What it does
Checks that function **kwargs arguments have type annotations.
## Why is this bad?
Type annotations are a good way to document the types of function arguments. They also
help catch bugs, when used alongside a type checker, by ensuring that the types of
any provided arguments match expectation.
## Example
```
def foo(**kwargs): ...
```
## Use instead:
```
def foo(**kwargs: int): ...
```
Loading
Oops, something went wrong.

0 comments on commit 815a363

Please sign in to comment.