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
1 change: 0 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches:
- main
- dev
- feat/archit/dev
pull_request:

Expand Down
88 changes: 88 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
[MASTER]
# Specify a configuration file.
load-plugins=

[MESSAGES CONTROL]
# C0111: Missing module/function/class docstring
# C0103: Invalid constant name
# R0913: Too many arguments
# R0914: Too many local variables
# R0904: Too many public methods
# W0212: Access to protected member
# W0611: Unused import
disable=missing-module-docstring,
missing-function-docstring,
missing-class-docstring,
invalid-name,
too-many-arguments,
too-many-locals,
too-many-public-methods,
protected-access,
unused-import,
too-few-public-methods,
duplicate-code,
line-too-long,

[FORMAT]
# Maximum number of characters on a single line.
max-line-length=120

# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$

[DESIGN]
# Maximum number of arguments for function / method
max-args=7

# Maximum number of attributes for a class
max-attributes=10

# Maximum number of locals in a function
max-locals=20

[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,TODO,XXX

[VARIABLE NAMES]
# Argument naming style
argument-naming-style=snake_case

# Attribute naming style
attr-naming-style=snake_case

# Class naming style
class-naming-style=PascalCase

# Constant naming style
const-naming-style=UPPER_CASE

# Function naming style
function-naming-style=snake_case

# Method naming style
method-naming-style=snake_case

# Module naming style
module-naming-style=snake_case

# Variable naming style
variable-naming-style=snake_case

[LOGGING]
# Format of logging format string.
logging-format-style=new

[BASIC]
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_,x,y,z,df,ax

# Include a hint for the correct naming format with invalid-name
include-naming-hint=yes

[SIMILARITIES]
# Ignore imports when computing similarities.
ignore-imports=yes

# Minimum lines number d a similarity to trigger off a duplication warning
min-similarity-lines=10
83 changes: 83 additions & 0 deletions examples/check_pylint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3
"""
Pylint checker script for RoboQA-Temporal

This script runs pylint on the specified directory to ensure code quality.

Usage:
python scripts/check_pylint.py # Check all source code
python scripts/check_pylint.py src # Check specific directory
python scripts/check_pylint.py --help # Show help
"""

import argparse
import subprocess
import sys
from pathlib import Path


def run_pylint(path: str, min_score: float = 7.0, strict: bool = False) -> int:
"""
Run pylint on specified path.

Args:
path: Path to check
min_score: Minimum score to pass
strict: If True, fail on any issues (uses higher threshold)

Returns:
Exit code
"""
cmd = [sys.executable, "-m", "pylint", path]

threshold = 9.0 if strict else min_score
cmd.extend(["--fail-under", str(threshold)])

result = subprocess.run(cmd, text=True)
return result.returncode


def main():
"""Main entry point."""
parser = argparse.ArgumentParser(description="Run pylint checks on RoboQA-Temporal")
parser.add_argument(
"path",
nargs="?",
default="src/roboqa_temporal",
help="Path to check (default: src/roboqa_temporal)",
)
parser.add_argument(
"--min-score",
type=float,
default=7.0,
help="Minimum pylint score to pass (default: 7.0)",
)
parser.add_argument(
"--strict",
action="store_true",
help="Use strict mode (fail-under 9.0)",
)

args = parser.parse_args()

check_path = Path(args.path)
if not check_path.is_absolute():
check_path = Path.cwd() / check_path

if not check_path.exists():
print(f"Error: Path does not exist: {check_path}", file=sys.stderr)
return 1

print(f"Running pylint on {check_path}...")
exit_code = run_pylint(str(check_path), args.min_score, args.strict)

if exit_code == 0:
print("\nPylint check passed!")
else:
print("\nPylint check failed!")

return exit_code


if __name__ == "__main__":
sys.exit(main())
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ dev = [
"black>=22.0.0",
"flake8>=4.0.0",
"mypy>=0.950",
"pylint>=3.0.0",
]

[project.scripts]
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ pyyaml>=6.0
tqdm>=4.62.0
tabulate>=0.9.0
lark-parser>=0.12.0
plotly>=5.0.0
plotly>=5.0.0
pylint>=3.0.0
84 changes: 84 additions & 0 deletions tests/test_pylint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""
Pylint integration tests for RoboQA-Temporal

This module provides pytest integration with pylint to check code quality.
"""

import subprocess
import sys
from pathlib import Path

import pytest


def get_python_files(directory: Path) -> list[Path]:
"""Get all Python files in the source directory."""
return list(directory.rglob("*.py"))


class TestPylint:
"""Pylint tests for code quality checking."""

@pytest.fixture(scope="session", autouse=True)
def source_dir(self):
"""Get the source directory path."""
return Path(__file__).resolve().parents[1] / "src" / "roboqa_temporal"

def test_pylint_src(self, source_dir):
"""Run pylint on source code."""
if not source_dir.exists():
pytest.skip(f"Source directory not found: {source_dir}")

result = subprocess.run(
[sys.executable, "-m", "pylint", str(source_dir), "--fail-under=7.0"],
capture_output=True,
text=True,
)

if result.returncode != 0:
pytest.fail(f"Pylint check failed:\n{result.stdout}\n{result.stderr}")

def test_pylint_tests(self):
"""Run pylint on test code with relaxed standards."""
test_dir = Path(__file__).resolve().parent

result = subprocess.run(
[
sys.executable,
"-m",
"pylint",
str(test_dir),
"--disable=missing-docstring",
"--fail-under=6.0",
],
capture_output=True,
text=True,
)

if result.returncode != 0:
print(f"\nPylint found issues in tests:\n{result.stdout}")


def test_pylint_single_module():
"""Test a specific module for pylint compliance."""
source_dir = Path(__file__).resolve().parents[1] / "src" / "roboqa_temporal"

if not source_dir.exists():
pytest.skip(f"Source directory not found: {source_dir}")

python_files = get_python_files(source_dir)
if not python_files:
pytest.skip("No Python files found")

detection_dir = source_dir / "detection"
if detection_dir.exists():
result = subprocess.run(
[sys.executable, "-m", "pylint", str(detection_dir)],
capture_output=True,
text=True,
)

lines = result.stdout.split("\n")
summary = [l for l in lines if "rated at" in l]
if summary:
print(f"\nDetection module pylint rating: {summary[0]}")