Repository navigation
Expand file tree
/
Copy pathruff-base.toml
More file actions
148 lines (141 loc) · 6.41 KB
/
Copy pathruff-base.toml
File metadata and controls
148 lines (141 loc) · 6.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Shared base ruff config for gradienthealth Python repos.
#
# Consuming repos extend this file from their own pyproject.toml by setting
# `extend = "path/to/ruff-base.toml"` under `[tool.ruff]`, then override only
# what they need (e.g. target-version, per-file ignores). Keep repo-specific
# knobs out of this file; it is the shared baseline every repo inherits.
line-length = 88
[format]
indent-style = "space"
quote-style = "double"
[lint]
# E501 (line-too-long) is off because the formatter owns code line length and
# W505/max-doc-length (79, below) governs docstring and comment width; a
# duplicate E501 report would only add noise.
#
# D100-D107 require docstrings on every module/class/function. The convention
# is no docstring over a low-content one (docstring minimalism). The remaining
# D rules still enforce shape and content when a docstring exists. D203/D213
# are mutually exclusive with D211/D212.
#
# TRY003 (raise-vanilla-args) flags a long literal message passed to an
# exception. It is ignored because it fights the house preference for a
# context-rich exception message that names what failed and with which values
# (`raise ValueError(f"batch_size must be > 0, got {n}")`); the rest of TRY,
# selected below, still enforces the error-handling discipline the house wants.
ignore = [
"E501",
"D100",
"D101",
"D102",
"D103",
"D104",
"D105",
"D106",
"D107",
"D203",
"D213",
"TRY003",
]
# ANN401 bans typing.Any in a parameter or return annotation: an Any in a
# signature opts that edge out of type checking. Only ANN401 is selected, not
# the whole ANN group, which would demand annotations everywhere.
#
# Complexity and size guardrails: C90 (cyclomatic, threshold in [lint.mccabe])
# and the PLR caps on returns/branches/statements.
#
# FBT (flake8-boolean-trap) flags boolean-typed positional arguments and bare
# True/False passed positionally -- a bool reads clearer by keyword. The whole
# group is selected so the trap is caught at the definition site (FBT001/002),
# not only at call sites (FBT003).
#
# PLC0415 (import-outside-top-level) bans in-function imports: an import inside
# a function body hides a dependency from the module header and is usually
# reflexive rather than a deliberate guard. A genuinely guarded import
# (heavy/optional/platform-specific) keeps its if/try guard at module top
# level.
#
# PLR0913 (too-many-arguments) is deliberately left out -- it fires on many
# legitimate wide signatures, and is better adopted once enforcement is scoped
# to a PR's changed lines, not the whole tree.
#
# DTZ (flake8-datetimez) flags a naive `datetime.now()`/`utcnow()`/`today()`
# with no tzinfo. A PHI/clinical shop that already makes durations a
# `timedelta` (RS007) should never store a naive timestamp: the missing zone is
# a latent bug the moment two environments disagree on local time.
#
# ERA (eradicate) flags commented-out code. The house comment rules
# (RS020/RS021/RS022/RS038) govern comment prose but have no rule against dead
# code left as a comment, the most common comment smell.
#
# G (flake8-logging-format) and LOG (flake8-logging) govern logging-call shape.
# G flags an f-string-, %-, or +-built log message; the argument should stay a
# lazy %-arg so the record renders only when it is emitted, which also keeps
# PHI out of an eagerly-rendered string -- the complement to RS008's
# PHI-safe-logging ban. LOG flags the deprecated `logging.warn` and `exc_info`
# misuse.
#
# N804/N805/N818 are cherry-picked from pep8-naming, not the whole N family,
# which would fight RS001's acronym casing and the house naming rules. N818
# wants an exception class name to end in `Error`; N804/N805 want the first
# argument of a classmethod/method to be `cls`/`self`.
#
# RET (flake8-return) flags an `else` after `return`, an unnecessary `else`,
# and a mismatched implicit/explicit return -- guard-clause hygiene that keeps
# a function's exits uniform.
#
# T20 (flake8-print) flags a `print()` in production; observability goes
# through logging, not stdout. A genuine CLI entrypoint that prints for the
# user is exempted with a per-file ignore in the consuming repo.
#
# TRY (tryceratops) flags error-handling smells -- a vanilla `raise Exception`,
# a long `try` body, a `return` inside `try`. TRY003 alone is turned off in the
# `ignore` list above.
select = [
"ANN401", # any-type (ban typing.Any in annotations)
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"C90", # mccabe cyclomatic complexity
"D", # pydocstyle (Google convention)
"DTZ", # flake8-datetimez (naive datetime without tzinfo)
"E", # pycodestyle errors
"ERA", # eradicate (commented-out code)
"F", # pyflakes
"FBT", # flake8-boolean-trap (boolean positional arguments)
"G", # flake8-logging-format (no f-string/%/+ log message)
"I", # isort
"LOG", # flake8-logging (logging.warn, exc_info misuse)
"N804", # first argument of a classmethod is cls
"N805", # first argument of a method is self
"N818", # exception class name ends in Error
"PLC0415", # import outside top-level (ban in-function imports)
"PLR0911", # too many return statements
"PLR0912", # too many branches
"PLR0915", # too many statements
"PT", # flake8-pytest-style
"RET", # flake8-return (else-after-return, redundant else)
"RUF", # ruff-specific
"SIM", # flake8-simplify
"T20", # flake8-print (print in production)
"TID", # flake8-tidy-imports (ban relative imports)
"TRY", # tryceratops (error-handling smells; TRY003 ignored)
"UP", # pyupgrade
"W", # pycodestyle warnings
]
# D401 enforces PEP 257's imperative one-line summary ("Return the lease", not
# "Returns the lease"). The house convention is the opposite -- a descriptive
# third-person summary, matching Google's own style guide rather than PEP 257
# -- so D401 stays off. The google convention's default ignore already excludes
# it.
[lint.pycodestyle]
# Docstring and comment prose fills to 79 (PEP 8), matching the RS009/RS035
# fill target. W505 backs those RS rules with ruff's own doc-length check;
# whether it runs tree-wide or only on a PR's changed lines follows how the
# consuming repo scopes ruff (a full-tree `ruff check` vs a diff-scoped one).
max-doc-length = 79
[lint.mccabe]
max-complexity = 10
[lint.pydocstyle]
convention = "google"
[lint.flake8-tidy-imports]
ban-relative-imports = "all"