-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Open
Labels
Enhancement ✨Improvement to a componentImprovement to a componentNeeds decision 🔒Needs a decision before implemention or rejectionNeeds a decision before implemention or rejection
Description
Current problem
When re-raising exceptions with raise ... from, developers often include the original error message in the new exception:
try:
save_config(data)
except OSError as err:
raise ConfigError(f"Failed to save config: {err}") from err
This is redundant because Python 3's exception chaining automatically preserves the original exception and its message via the cause attribute. The result is duplicate information in logs and tracebacks:
ConfigError: Failed to save config: [Errno 2] No such file or directory: 'config.json'
The above exception was the direct cause of the following exception:
...
OSError: [Errno 2] No such file or directory: 'config.json'
Currently, pylint has raise-missing-from (W0707) to suggest using from, but nothing to detect this redundant pattern once from is used.
Desired solution
Add a new check redundant-exception-message (W0720) that detects when the chained exception variable is included in the new exception's message.
Detected patterns:
raise ConfigError(f"Failed: {err}") from err # f-string with {err}
raise ConfigError(f"Failed: {str(err)}") from err # f-string with {str(err)}
raise ConfigError("Failed: " + str(err)) from err # concatenation
raise ConfigError(str(err)) from err # str(err) as argument
Recommended:
raise ConfigError("Failed to save configuration") from err
Or, if specific context is needed:
raise ConfigError(f"Config file not found: {path}") from err # OK: uses path, not err
Additional context
- This follows Python best practices for exception chaining (PEP 3134)
- Avoids duplicate information in error logs
- Complements the existing raise-missing-from check
- Implementation ready with tests and documentation
Metadata
Metadata
Assignees
Labels
Enhancement ✨Improvement to a componentImprovement to a componentNeeds decision 🔒Needs a decision before implemention or rejectionNeeds a decision before implemention or rejection