Skip to content

Latest commit

 

History

History
106 lines (94 loc) · 5.48 KB

pep-8-compliance.md

File metadata and controls

106 lines (94 loc) · 5.48 KB

PEP 8 compliance

PEP 8 is a set of rules for writing Pythonic code. To ensure that the code adheres to these rules, you can use a static analysis tool called a linter. While the two most commonly used Python linters are pylint and flake-8, I prefer to use a different one: Ruff.

Ruff

Ruff has several advantages:

  • Support for pylint and flake-8 rules.
  • Faster checking, 10 to 100 times faster than pylint and flake-8.
  • No need for additional plugins, because they are already shipped with Ruff.

Usage

ruff .

Configuration

Add the following configuration to your pyproject.toml, with "YOUR PACKAGE NAME" in tool.ruff.isort replaced with your package name (of course), and the same for "MAYBE PRIVATE NAME OF YOUR PACKAGE" if you have some private packages.

[tool.ruff]
select = [
    "A", # flake8-builtins (redefinition of bultins)
    "ANN", # flake8-annotations (type annotations are everywhere)
    "ARG", # flake8-unused-arguments (unused argument in function/method/class/lambda)
    "B", # flake8-bugbear (bugs & design problems)
    "B9", # flake8-bugbear strict (bugs & design problems)
    "BLE", # flake8-blind-except (no "except:" or "except Exception:")
    # "COM", # flake8-commas (force trailing commas) -> unelegant
    "C4", # flake8-comprehensions (better list/set/dict comprehensions)
    "C90", # McCabe (code complexity)
    "D", # pydocstyle (documentation style)
    "DJ", # flake8-django (practices on Django)
    "DTZ", # flake8-datetimez (usage of unsafe naive datetime class)
    "E", # pycodestyle (violation of PEP-8)
    "EM", # flake8-errmsg (format error messages)
    "EXE", # flake8-executable (executable permissions and shebangs)
    "ERA", # eradicate (no commented-out code)
    "F", # pyflakes (invalid Python code)
    "FBT", # flake8-boolean-trap (misusage of booleans in function declaration & calls)
    "G", # flake8-logging-format (logging format strings)
    "I", # isort (import order)
    "ICN", # flake8-import-conventions (how certain packages should be imported or aliased)
    # "INP", # flake8-no-pep420 (ban PEP-420 implicit namespace packages) -> long live implicit namespace packages!
    "INT", # flake8-gettext (f-string resolved before function calls)
    "ISC", # flake8-implicit-str-concat (string literal concatenation)
    "N", # pep8-naming (naming conventions)
    "NPY", # NumPy-specific rules (e.g. deprecated-type-alias and legacy-random)
    "PD", # pandas-vet (pandas code)
    "PIE", # flake8-pie (miscellaneous lints)
    "PGH", # pygrep-hooks (miscellaneous lints, e.g. "use specific rule codes when using noqa")
    "PL", # Pylint (static code analyser)
    "PT", # flake8-pytest-style (style issues or inconsistencies with pytest-based tests)
    "PTH", # flake8-use-pathlib (use of functions that can be replaced by pathlib module)
    "PYI", # flake8-pyi (provide specializations for type hinting stub files)
    "Q0", # flake8-quotes (avoid escaping quotes)
    "RSE", # flake8-raise (improvements for raise statements)
    "RET", # flake8-return (check return values)
    "RUF", # ruff-specific rules
    "S", # flake8-bandit (security)
    "SIM", # flake8-simplify (tips to simplify the code)
    "SLF", # flake8-self (private member access)
    "T10", # flake8-debugger
    "T20", # flake8-print (no print nor pprint)
    "TCH", # flake8-type-checking (move import only intended for type-checking in "if TYPE_CHECKING" blocs)
    "TID", # flake8-tidy-imports (ordonated imports)
    "TRY", # tryceratops (exception handling AntiPatterns)
    "UP", # pyupgrade (upgrate syntax for newer versions of Python)
    "YTT", # flake8-2020 (misuse of sys.version and sys.version_info)
    "W" # pycodestyle (violation of PEP-8)
]
ignore = [
    "ANN101", # missing type annotation for self, but hinting self all the time is useless
    "ANN102", # missing type annotation for cls but hinting cls all the time is useless
    "ANN401", # disallows Any, but some elements should be Any when they are external
    "B024",   # forces abstract classes to have at least one abstract method, but sometimes a class is virtually abstract
    "D100",   # docstrings at the top of public modules, but most of the time it's useless
    "D105",   # docstrings on magic methods, useless docstrings are well known 
    "E501",   # line size, but bug-bear already set it with a tolerance of 10% (B950)
    "PD011", # use .to_numpy instead of .values, but raises a lot of false positives
]

[tool.ruff.per-file-ignores]
"docs/conf.py" = [
    "A001" # redefine some builtins (like "copyright") is OK in docs
]
"test*/" = [
    "ARG", # some arguments are unused in tests functions but useful (e.g. mocks)
    "FBT001", # boolean positional arg in function definition is ok for test functions because it's for parametrize so never call by a user
    "PLR0913", # no issue for a test function to have a lot of args
    "PLR2004", # magic value in comparison is OK for tests
    "S101", # asserts are OK for tests
    "SLF001" # accessing private members is OK for tests
]

[tool.ruff.pydocstyle]
convention = "google"

[tool.ruff.isort]
known-first-party = ["YOUR PACKAGE NAME", "MAYBE PRIVATE NAME OF YOUR PACKAGE"]