You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+72Lines changed: 72 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -154,6 +154,78 @@ All code must follow secure-by-default principles. Review every change against t
154
154
- Do not add new dependencies without reviewing their security posture (maintained? known CVEs?)
155
155
- Avoid transitive dependency bloat — prefer stdlib solutions when the alternative is a single-function dependency
156
156
157
+
## Code quality (SonarQube / Codacy compliance)
158
+
159
+
All code must satisfy common static-analysis rules enforced by SonarQube and Codacy. Review each change against the checklist below.
160
+
161
+
### Complexity & size
162
+
- Cyclomatic complexity per function: ≤ 15 (hard cap 20). Break large branches into helpers
163
+
- Cognitive complexity per function: ≤ 15. Flatten nested `if`/`for`/`try` chains with early returns or guard clauses
164
+
- Function length: ≤ 75 lines of code (excluding docstring / blank lines). Extract helpers past that
165
+
- Parameter count: ≤ 7 per function/method. Use a dataclass or typed dict when more are needed
166
+
- Nesting depth: ≤ 4 levels of `if`/`for`/`while`/`try`. Refactor with early returns instead of pyramids
167
+
- File length: ≤ 1000 lines — split modules past that
168
+
- Class `__init__`: keep attribute count reasonable; if a class has > 15 instance attributes, split responsibilities
169
+
170
+
### Exception handling
171
+
- Never use bare `except:` — always specify exception types
172
+
- Avoid catching `Exception` or `BaseException` unless immediately re-raising or logging and re-raising with context
173
+
- Never `pass` silently inside `except` — log the error via `pybreeze_logger` (at minimum `.debug()`) with context
174
+
- Do not `return` / `break` / `continue` inside a `finally` block — it swallows exceptions
175
+
- Custom exceptions must inherit from `ITEException`; never `raise Exception(...)` directly
176
+
- Use `raise ... from err` (or `raise ... from None`) when re-raising to preserve / suppress the chain explicitly
177
+
178
+
### Pythonic correctness
179
+
- Compare with `None` using `is` / `is not`, never `==` / `!=`
180
+
- Type checks use `isinstance(obj, T)`, never `type(obj) == T`
181
+
- Never use mutable default arguments (`def f(x=[])`) — use `None` and initialise inside
182
+
- Prefer f-strings over `%` formatting or `str.format()`
183
+
- Use context managers (`with open(...) as f:`) for every file / socket / lock — never leave resources to GC
184
+
- Use `enumerate()` instead of `range(len(...))` when the index is needed alongside the item
185
+
- Use `dict.get(key, default)` instead of `key in dict and dict[key]` patterns
186
+
- Use set / dict comprehensions when clearer than manual loops; avoid comprehensions with side effects
187
+
188
+
### Naming & style (PEP 8)
189
+
-`snake_case` for functions, methods, variables, module names
190
+
-`PascalCase` for classes
191
+
-`UPPER_SNAKE_CASE` for module-level constants
192
+
-`_leading_underscore` for protected / internal members; never use `__dunder__` for custom attributes
193
+
- No single-letter names except loop indices (`i`, `j`) or conventional math (`x`, `y`)
194
+
- Do not shadow built-ins (`id`, `type`, `list`, `dict`, `input`, `file`, `open`, etc.) — rename the local variable
195
+
196
+
### Duplication & dead code
197
+
- String literal used 3+ times in the same module → extract a module-level constant
198
+
- Identical 6+ line blocks in 2+ places → extract a helper function
199
+
- Remove unused imports, unused parameters, unused local variables, unreachable code after `return` / `raise`
200
+
- No commented-out code blocks — delete them (git history is the archive)
201
+
- No `TODO` / `FIXME` / `XXX` without an accompanying issue reference (`# TODO(#123): ...`)
202
+
203
+
### Logging, printing, assertions
204
+
- Never use `print()` for diagnostics in library / runtime code — use `pybreeze_logger`
205
+
- Use lazy logging (`logger.debug("x=%s", x)`) — avoid eager f-string formatting inside log calls on hot paths
206
+
- Never use `assert` for runtime validation (Python strips assertions with `-O`). Use explicit `if … raise …` instead; `assert` is only for test code
207
+
208
+
### Hardcoded values & secrets
209
+
- No hardcoded passwords, tokens, API keys, or secrets — use env vars or a config file excluded from VCS
210
+
- No hardcoded IP addresses or hostnames outside of `localhost` / documented loopback — use config
211
+
- Magic numbers (except 0, 1, -1) should be named constants when repeated or non-obvious
212
+
213
+
### Boolean & return hygiene
214
+
- Replace `if cond: return True else: return False` with `return bool(cond)` or `return cond`
215
+
- Replace `if x == True` / `if x == False` with `if x` / `if not x`
216
+
- A function should have a consistent return type — never mix `return value` and bare `return` (returns `None`) on meaningful paths unless explicitly documented
217
+
- Do not return inside a generator function (`yield` + `return value` is a syntax pitfall)
218
+
219
+
### Imports
220
+
- One import per line for `import` statements; grouped `from x import a, b` is fine
- No wildcard imports (`from x import *`) outside of `__init__.py` re-exports
223
+
- No relative imports beyond one level (`from ..pkg import x` OK, `from ...pkg import x` avoid)
224
+
225
+
### Running the linters
226
+
- Before committing any non-trivial change, run `ruff check pybreeze/` locally to catch these rules — `ruff` covers the majority of SonarQube/Codacy Python rules
227
+
- When adding a new rule exception, justify it in a `# noqa: RULE` comment with a short reason — never blanket-disable
0 commit comments