Python¶
Python's zen principles come directly from PEP 20 — The Zen of Python. If you've ever typed import this in a Python REPL, you've seen them. MCP Zen of Languages turns these aphorisms into actionable code analysis — 12 principles enforced by 23 detectors.
Deepest analysis available
Python is the only language with full AST parsing, cyclomatic complexity measurement, maintainability index scoring, and dependency graph analysis. Other languages use regex-based detection.
Optional External Tool Augmentation¶
Consent-first external tooling
External tool execution is optional and disabled by default. Use
--enable-external-tools (CLI) or enable_external_tools=true (MCP)
to opt in. Missing tools should return recommendations; no automatic
installs occur during analysis.
| Tool | Default invocation | Output |
|---|---|---|
ruff |
ruff check --stdin-filename stdin.py - |
Text / structured stderr |
Temporary runner fallback
For temporary execution via package runners, use
--allow-temporary-runners (CLI) or allow_temporary_runners=true (MCP).
Zen Principles¶
20 principles across 11 categories, drawn from PEP 20 - The Zen of Python.
Architecture · 1 principle Clarity · 1 principle Complexity · 1 principle Consistency · 1 principle Correctness · 2 principles Design · 2 principles Error Handling · 1 principle Idioms · 2 principles Organization · 2 principles Readability · 5 principles Structure · 2 principles
| Rule ID | Principle | Category | Severity | Dogma |
|---|---|---|---|---|
python-001 |
Beautiful is better than ugly | Readability | 4 | ZEN-UNAMBIGUOUS-NAME |
python-002 |
Explicit is better than implicit | Clarity | 7 | ZEN-EXPLICIT-INTENT |
python-003 |
Simple is better than complex | Complexity | 8 | ZEN-PROPORTIONATE-COMPLEXITY, ZEN-RETURN-EARLY, ZEN-RIGHT-ABSTRACTION |
python-004 |
Complex is better than complicated | Architecture | 7 | ZEN-RIGHT-ABSTRACTION, ZEN-PROPORTIONATE-COMPLEXITY |
python-005 |
Flat is better than nested | Structure | 8 | ZEN-RETURN-EARLY |
python-006 |
Sparse is better than dense | Readability | 5 | ZEN-UNAMBIGUOUS-NAME, ZEN-VISIBLE-STATE |
python-007 |
Readability counts | Readability | 9 | ZEN-UNAMBIGUOUS-NAME |
python-008 |
Special cases aren't special enough to break the rules | Consistency | 6 | ZEN-EXPLICIT-INTENT, ZEN-FAIL-FAST |
python-009 |
Errors should never pass silently | Error Handling | 9 | ZEN-FAIL-FAST, ZEN-EXPLICIT-INTENT |
python-010 |
In the face of ambiguity, refuse the temptation to guess | Correctness | 7 | ZEN-EXPLICIT-INTENT |
python-011 |
There should be one-- and preferably only one --obvious way to do it | Idioms | 6 | ZEN-RIGHT-ABSTRACTION, ZEN-VISIBLE-STATE |
python-012 |
Namespaces are one honking great idea | Organization | 7 | ZEN-STRICT-FENCES, ZEN-UNAMBIGUOUS-NAME |
python-013 |
Practicality beats purity | Design | 5 | ZEN-RIGHT-ABSTRACTION, ZEN-PROPORTIONATE-COMPLEXITY |
python-014 |
Unless explicitly silenced | Correctness | 8 | ZEN-EXPLICIT-INTENT, ZEN-FAIL-FAST |
python-015 |
Now is better than never | Structure | 4 | ZEN-RETURN-EARLY, ZEN-RUTHLESS-DELETION |
python-016 |
Although never is often better than right now | Design | 5 | ZEN-RIGHT-ABSTRACTION, ZEN-FAIL-FAST, ZEN-RUTHLESS-DELETION |
python-017 |
If the implementation is hard to explain, it's a bad idea | Readability | 6 | ZEN-UNAMBIGUOUS-NAME |
python-018 |
If the implementation is easy to explain, it may be a good idea | Readability | 3 | ZEN-UNAMBIGUOUS-NAME, ZEN-PROPORTIONATE-COMPLEXITY |
python-019 |
Although that way may not be obvious at first unless you're Dutch | Idioms | 5 | ZEN-RIGHT-ABSTRACTION |
python-020 |
Let's do more of those | Organization | 6 | ZEN-STRICT-FENCES, ZEN-UNAMBIGUOUS-NAME |
python-001 — Beautiful is better than ugly
Code should be aesthetically pleasing and well-formatted
Universal Dogmas: ZEN-UNAMBIGUOUS-NAME
Common Violations:
- Inconsistent indentation
- Poor naming conventions
- Lack of whitespace around operators
- Overly compact code
Thresholds:
| Parameter | Default |
|---|---|
max_line_length |
88 |
naming_convention |
snake_case |
min_identifier_length |
2 |
python-002 — Explicit is better than implicit
Code behavior should be obvious and unambiguous
Universal Dogmas: ZEN-EXPLICIT-INTENT
Common Violations:
- Using global variables without declaration
- Implicit type conversions
- Magic numbers without constants
- Overuse of * imports
- Hidden side effects in functions
Detectable Patterns:
from module import *global keyword abusefunctions modifying arguments without clear indication
python-003 — Simple is better than complex
Favor straightforward solutions over complicated ones
Universal Dogmas: ZEN-PROPORTIONATE-COMPLEXITY, ZEN-RETURN-EARLY, ZEN-RIGHT-ABSTRACTION
Common Violations:
- High cyclomatic complexity (>10)
- Overly nested comprehensions
- Unnecessary abstraction layers
- Complex one-liners
Thresholds:
| Parameter | Default |
|---|---|
max_cyclomatic_complexity |
10 |
python-004 — Complex is better than complicated
When complexity is necessary, keep it organized and understandable
Universal Dogmas: ZEN-RIGHT-ABSTRACTION, ZEN-PROPORTIONATE-COMPLEXITY
Common Violations:
- Tangled dependencies
- Unclear module boundaries
- Mixed concerns in single class
python-005 — Flat is better than nested
Avoid deep nesting of control structures
Universal Dogmas: ZEN-RETURN-EARLY
Common Violations:
- Nesting depth > 3 levels
- Multiple nested loops
- Deeply nested if-else chains
Thresholds:
| Parameter | Default |
|---|---|
max_nesting_depth |
3 |
python-006 — Sparse is better than dense
Code should have appropriate spacing and not be cramped
Universal Dogmas: ZEN-UNAMBIGUOUS-NAME, ZEN-VISIBLE-STATE
Common Violations:
- Multiple statements on one line
- Overly compact expressions
- Lack of blank lines between logical sections
Thresholds:
| Parameter | Default |
|---|---|
max_statements_per_line |
1 |
min_blank_lines_between_defs |
1 |
python-007 — Readability counts
Code is read more often than written
Universal Dogmas: ZEN-UNAMBIGUOUS-NAME
Common Violations:
- Functions longer than 50 lines
- Classes longer than 300 lines
- Unclear variable names (a, b, x)
- Missing docstrings for public APIs
Thresholds:
| Parameter | Default |
|---|---|
max_function_length |
50 |
max_class_length |
300 |
python-008 — Special cases aren't special enough to break the rules
Maintain consistency even for edge cases
Universal Dogmas: ZEN-EXPLICIT-INTENT, ZEN-FAIL-FAST
Common Violations:
- Inconsistent error handling patterns
- Different naming conventions within same module
- Special-case code paths without justification
Thresholds:
| Parameter | Default |
|---|---|
max_naming_styles |
1 |
python-009 — Errors should never pass silently
Always handle errors explicitly
Universal Dogmas: ZEN-FAIL-FAST, ZEN-EXPLICIT-INTENT
Common Violations:
- Bare except clauses
- Catching Exception without handling
- Ignoring return codes
- Empty except blocks
Detectable Patterns:
except: passexcept Exception: pass
python-010 — In the face of ambiguity, refuse the temptation to guess
Be explicit rather than making assumptions
Universal Dogmas: ZEN-EXPLICIT-INTENT
Common Violations:
- Implicit type assumptions
- Unclear function contracts
- Missing input validation
Thresholds:
| Parameter | Default |
|---|---|
require_type_hints |
True |
python-011 — There should be one-- and preferably only one --obvious way to do it
Prefer pythonic idioms over alternatives
Universal Dogmas: ZEN-RIGHT-ABSTRACTION, ZEN-VISIBLE-STATE
Common Violations:
- Using range(len()) instead of enumerate
- Manual iteration instead of list comprehensions
- Not using context managers for resources
- Multiple implementations of same logic
Detectable Patterns:
for i in range(len(list))file without 'with' statement
python-012 — Namespaces are one honking great idea
Use namespaces to organize code clearly
Universal Dogmas: ZEN-STRICT-FENCES, ZEN-UNAMBIGUOUS-NAME
Common Violations:
- Polluting global namespace
- Too many items in all
- Deep module nesting without purpose
Thresholds:
| Parameter | Default |
|---|---|
max_top_level_symbols |
25 |
max_exports |
20 |
python-013 — Practicality beats purity
Prefer simple, practical solutions over excessive abstraction
Universal Dogmas: ZEN-RIGHT-ABSTRACTION, ZEN-PROPORTIONATE-COMPLEXITY
Common Violations:
- Over-engineered ABC/Protocol hierarchies
- Premature abstraction with few implementations
python-014 — Unless explicitly silenced
Only suppress exceptions when suppression is intentional and documented
Universal Dogmas: ZEN-EXPLICIT-INTENT, ZEN-FAIL-FAST
Common Violations:
- Bare except clauses
- Silent exception catching with pass
python-015 — Now is better than never
Address TODOs and stubs promptly
Universal Dogmas: ZEN-RETURN-EARLY, ZEN-RUTHLESS-DELETION
Common Violations:
- TODO/FIXME/HACK/XXX comments left unresolved
python-016 — Although never is often better than right now
Document why functionality is deferred rather than raising bare NotImplementedError
Universal Dogmas: ZEN-RIGHT-ABSTRACTION, ZEN-FAIL-FAST, ZEN-RUTHLESS-DELETION
Common Violations:
- Undocumented NotImplementedError stubs
python-017 — If the implementation is hard to explain, it's a bad idea
Complex code must be documented
Universal Dogmas: ZEN-UNAMBIGUOUS-NAME
Common Violations:
- Functions without docstrings
python-018 — If the implementation is easy to explain, it may be a good idea
Even simple public functions benefit from docstrings
Universal Dogmas: ZEN-UNAMBIGUOUS-NAME, ZEN-PROPORTIONATE-COMPLEXITY
Common Violations:
- Public functions without docstrings
python-019 — Although that way may not be obvious at first unless you're Dutch
Use idiomatic Python constructs that may not be obvious to newcomers
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- Using range(len()) instead of enumerate()
- Comparing with == True/False instead of direct boolean checks
python-020 — Let's do more of those
Actively use namespaces to keep modules focused and maintainable
Universal Dogmas: ZEN-STRICT-FENCES, ZEN-UNAMBIGUOUS-NAME
Common Violations:
- Polluting global namespace
- Too many items in all
- Monolithic modules instead of focused namespaces
Thresholds:
| Parameter | Default |
|---|---|
max_top_level_symbols |
25 |
max_exports |
20 |
Detector Catalog¶
Architecture¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| GodClassDetector | Detect God classes — classes with too many methods or lines of code | python-004 |
| CircularDependencyDetector | Detect circular import dependencies across modules | python-004 |
| DeepInheritanceDetector | Detect class hierarchies that exceed a safe inheritance depth | python-004 |
Clarity¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| MagicMethodDetector | Detect classes that overload too many dunder (magic) methods | python-002 |
| StarImportDetector | Detect wildcard from X import * statements that pollute the module namespace |
python-002 |
| MagicNumberDetector | Detect excessive use of unexplained numeric literals (magic numbers) | python-002 |
Complexity¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| CyclomaticComplexityDetector | Detect functions whose cyclomatic complexity exceeds the configured threshold | python-003 |
| ComplexOneLinersDetector | Detect overly dense one-liner expressions that sacrifice readability | python-003 |
Consistency¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| ConsistencyDetector | Detect mixed naming conventions within a single module | python-008 |
Correctness¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| ExplicitnessDetector | Detect function parameters missing type annotations | python-010 |
| PythonExplicitSilenceDetector | Detects bare except clauses and silently caught exceptions | python-014 |
Design¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| PythonPracticalityDetector | Flags over-engineered abstractions like ABCs with likely few implementations | python-013 |
| PythonPrematureImplDetector | Detects raise NotImplementedError stubs without documentation |
python-016 |
Error Handling¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| BareExceptDetector | Detect bare except: clauses and silently swallowed exceptions |
python-009 |
Idioms¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| FeatureEnvyDetector | Detect methods that access another object's data more than their own | python-011 |
| DuplicateImplementationDetector | Detect identical or near-identical function implementations across files | python-011 |
| ContextManagerDetector | Detect open() calls not wrapped in a with context manager |
python-011 |
| PythonIdiomDetector | Detects non-idiomatic Python patterns like range(len(...)) and == True |
python-019 |
Organization¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| NamespaceUsageDetector | Detect modules with too many top-level symbols or __all__ exports |
python-012, python-020 |
Readability¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| NameStyleDetector | Detect function and variable names that violate Python's snake_case convention |
python-001 |
| LongFunctionDetector | Detect functions whose line count exceeds the configured maximum | python-007 |
| ShortVariableNamesDetector | Detect variables and loop targets with names shorter than the configured minimum | python-007 |
| ClassSizeDetector | Detect classes whose line count exceeds the configured maximum | python-007 |
| LineLengthDetector | Detect source lines that exceed a configured character limit | python-001 |
| SparseCodeDetector | Detect lines packing multiple statements separated by semicolons | python-006 |
| DocstringDetector | Detect top-level functions and classes missing a docstring | python-007 |
| PythonComplexUndocumentedDetector | Detects functions missing docstrings | python-017 |
| PythonSimpleDocumentedDetector | Detects public functions (not starting with _) missing docstrings |
python-018 |
Structure¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| NestingDepthDetector | Detect code blocks with excessive indentation depth and nested loops | python-005 |
| PythonTodoStubDetector | Detects TODO, FIXME, HACK, and XXX comments left in source code | python-015 |
Principle → Detector Wiring
%%{init: {"theme": "base", "flowchart": {"useMaxWidth": false, "htmlLabels": true, "nodeSpacing": 40, "rankSpacing": 60}}}%%
graph TD
python_001["python-001<br/>Beautiful is better than ..."]
python_002["python-002<br/>Explicit is better than i..."]
python_003["python-003<br/>Simple is better than com..."]
python_004["python-004<br/>Complex is better than co..."]
python_005["python-005<br/>Flat is better than neste..."]
python_006["python-006<br/>Sparse is better than den..."]
python_007["python-007<br/>Readability counts"]
python_008["python-008<br/>Special cases aren't spec..."]
python_009["python-009<br/>Errors should never pass ..."]
python_010["python-010<br/>In the face of ambiguity,..."]
python_011["python-011<br/>There should be one-- and..."]
python_012["python-012<br/>Namespaces are one honkin..."]
python_013["python-013<br/>Practicality beats purity"]
python_014["python-014<br/>Unless explicitly silence..."]
python_015["python-015<br/>Now is better than never"]
python_016["python-016<br/>Although never is often b..."]
python_017["python-017<br/>If the implementation is ..."]
python_018["python-018<br/>If the implementation is ..."]
python_019["python-019<br/>Although that way may not..."]
python_020["python-020<br/>Let's do more of those"]
det_BareExceptDetector["Bare Except"]
python_009 --> det_BareExceptDetector
det_CircularDependencyDetector["Circular Dependency"]
python_004 --> det_CircularDependencyDetector
det_ClassSizeDetector["Class Size"]
python_007 --> det_ClassSizeDetector
det_ComplexOneLinersDetector["Complex One<br/>Liners"]
python_003 --> det_ComplexOneLinersDetector
det_ConsistencyDetector["Consistency"]
python_008 --> det_ConsistencyDetector
det_ContextManagerDetector["Context Manager"]
python_011 --> det_ContextManagerDetector
det_CyclomaticComplexityDetector["Cyclomatic Complexity"]
python_003 --> det_CyclomaticComplexityDetector
det_DeepInheritanceDetector["Deep Inheritance"]
python_004 --> det_DeepInheritanceDetector
det_DocstringDetector["Docstring"]
python_007 --> det_DocstringDetector
det_DuplicateImplementationDetector["Duplicate Implementation"]
python_011 --> det_DuplicateImplementationDetector
det_ExplicitnessDetector["Explicitness"]
python_010 --> det_ExplicitnessDetector
det_FeatureEnvyDetector["Feature Envy"]
python_011 --> det_FeatureEnvyDetector
det_GodClassDetector["God Class"]
python_004 --> det_GodClassDetector
det_LineLengthDetector["Line Length"]
python_001 --> det_LineLengthDetector
det_LongFunctionDetector["Long Function"]
python_007 --> det_LongFunctionDetector
det_MagicMethodDetector["Magic Method"]
python_002 --> det_MagicMethodDetector
det_MagicNumberDetector["Magic Number"]
python_002 --> det_MagicNumberDetector
det_NameStyleDetector["Name Style"]
det_NamespaceUsageDetector["Namespace Usage"]
python_012 --> det_NamespaceUsageDetector
python_020 --> det_NamespaceUsageDetector
det_NestingDepthDetector["Nesting Depth"]
python_005 --> det_NestingDepthDetector
det_PythonComplexUndocumentedDetector["Python Complex<br/>Undocumented"]
python_017 --> det_PythonComplexUndocumentedDetector
det_PythonExplicitSilenceDetector["Python Explicit<br/>Silence"]
python_014 --> det_PythonExplicitSilenceDetector
det_PythonIdiomDetector["Python Idiom"]
python_019 --> det_PythonIdiomDetector
det_PythonPracticalityDetector["Python Practicality"]
python_013 --> det_PythonPracticalityDetector
det_PythonPrematureImplDetector["Python Premature<br/>Impl"]
python_016 --> det_PythonPrematureImplDetector
det_PythonSimpleDocumentedDetector["Python Simple<br/>Documented"]
python_018 --> det_PythonSimpleDocumentedDetector
det_PythonTodoStubDetector["Python Todo<br/>Stub"]
python_015 --> det_PythonTodoStubDetector
det_ShortVariableNamesDetector["Short Variable<br/>Names"]
python_007 --> det_ShortVariableNamesDetector
det_SparseCodeDetector["Sparse Code"]
python_006 --> det_SparseCodeDetector
det_StarImportDetector["Star Import"]
python_002 --> det_StarImportDetector
Detector Class Hierarchy
%%{init: {"theme": "base"}}%%
classDiagram
direction TB
class ViolationDetector {
<<abstract>>
+detect(context, config)
}
class det_01["Bare Except"]
ViolationDetector <|-- det_01
class det_02["Circular Dependency"]
ViolationDetector <|-- det_02
class det_03["Class Size"]
ViolationDetector <|-- det_03
class det_04["Complex One Liners"]
ViolationDetector <|-- det_04
class det_05["Consistency"]
ViolationDetector <|-- det_05
class det_06["Context Manager"]
ViolationDetector <|-- det_06
class det_07["Cyclomatic Complexity"]
ViolationDetector <|-- det_07
class det_08["Deep Inheritance"]
ViolationDetector <|-- det_08
class det_09["Docstring"]
ViolationDetector <|-- det_09
class det_10["Duplicate Implementation"]
ViolationDetector <|-- det_10
class det_11["Explicitness"]
ViolationDetector <|-- det_11
class det_12["Feature Envy"]
ViolationDetector <|-- det_12
class det_13["God Class"]
ViolationDetector <|-- det_13
class det_14["Line Length"]
ViolationDetector <|-- det_14
class det_15["Long Function"]
ViolationDetector <|-- det_15
class det_16["Magic Method"]
ViolationDetector <|-- det_16
class det_17["Magic Number"]
ViolationDetector <|-- det_17
class det_18["Name Style"]
ViolationDetector <|-- det_18
class det_19["Namespace Usage"]
ViolationDetector <|-- det_19
class det_20["Nesting Depth"]
ViolationDetector <|-- det_20
class det_21["Python Complex Undocumented"]
ViolationDetector <|-- det_21
class det_22["Python Explicit Silence"]
ViolationDetector <|-- det_22
class det_23["Python Idiom"]
ViolationDetector <|-- det_23
class det_24["Python Practicality"]
ViolationDetector <|-- det_24
class det_25["Python Premature Impl"]
ViolationDetector <|-- det_25
class det_26["Python Simple Documented"]
ViolationDetector <|-- det_26
class det_27["Python Todo Stub"]
ViolationDetector <|-- det_27
class det_28["Short Variable Names"]
ViolationDetector <|-- det_28
class det_29["Sparse Code"]
ViolationDetector <|-- det_29
class det_30["Star Import"]
ViolationDetector <|-- det_30
Analysis Pipeline
%%{init: {"theme": "base", "flowchart": {"useMaxWidth": false, "htmlLabels": true, "nodeSpacing": 50, "rankSpacing": 70}}}%%
flowchart TD
Source(["Source Code"]) --> Parse["Parse & Tokenize"]
Parse --> Metrics["Compute Metrics"]
Metrics --> Pipeline{"30 Detectors"}
Pipeline --> Collect["Aggregate Violations"]
Collect --> Result(["AnalysisResult<br/>20 principles"])
Analysis States
%%{init: {"theme": "base"}}%%
stateDiagram-v2
[*] --> Ready
Ready --> Parsing : analyze(code)
Parsing --> Computing : AST ready
Computing --> Detecting : metrics ready
Detecting --> Reporting : 30 detectors run
Reporting --> [*] : AnalysisResult
Parsing --> Reporting : parse error (best-effort)
Configuration¶
languages:
python:
enabled: true
pipeline:
- type: cyclomatic_complexity
max_cyclomatic_complexity: 10
- type: complex_one_liners
max_for_clauses: 1
max_line_length: 120
- type: nesting_depth
max_nesting_depth: 3
- type: long_functions
max_function_length: 50
- type: short_variable_names
min_identifier_length: 3
allowed_loop_names: ['i', 'j', 'k', 'x', 'y']
- type: god_classes
max_methods: 10
max_class_length: 300
- type: magic_methods
max_magic_methods: 3
- type: deep_inheritance
max_depth: 3
- type: feature_envy
min_occurrences: 3
- type: class_size
max_class_length: 300
- type: magic_number
max_magic_numbers: 0
- type: line_length
max_line_length: 88
- type: sparse_code
max_statements_per_line: 1
min_blank_lines_between_defs: 1
- type: consistency
max_naming_styles: 1
- type: explicitness
require_type_hints: True
- type: namespace_usage
max_top_level_symbols: 25
max_exports: 20
Start relaxed, tighten over time
For legacy codebases, start with max_cyclomatic_complexity: 15 and max_function_length: 80, then lower thresholds as you remediate.
See Also¶
- Configuration — Full config reference and override strategies
- Understanding Violations — How to interpret severity scores
- Prompt Generation — Generate AI remediation prompts from violations