feat(errors): add DBusFastError common base class#634
Conversation
Introduce DBusFastError so callers can catch every dbus-fast exception with one except clause instead of listing each error class individually or wrapping calls in separate try/except blocks. All existing error classes now inherit from DBusFastError. Classes that previously derived from ValueError or TypeError still do — they now use multiple inheritance so existing handlers keep working unchanged. Fixes #507 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #634 +/- ##
==========================================
- Coverage 86.11% 86.06% -0.06%
==========================================
Files 29 29
Lines 3487 3488 +1
Branches 602 602
==========================================
- Hits 3003 3002 -1
- Misses 299 300 +1
- Partials 185 186 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new DBusFastError base exception to unify dbus-fast’s public exception hierarchy, allowing callers to catch library-specific errors with a single except DBusFastError while keeping compatibility with existing except ValueError / except TypeError handlers.
Changes:
- Added
DBusFastError(Exception)and updated existing dbus-fast exception classes to inherit from it (with multiple inheritance for the historicalValueError/TypeErrorsubclasses). - Exported
DBusFastErrorfrom the package root (dbus_fast.__init__). - Added a new test module validating subclass relationships and message formatting for key exceptions.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/dbus_fast/errors.py |
Introduces DBusFastError and updates existing exception classes to inherit from it. |
src/dbus_fast/__init__.py |
Re-exports DBusFastError from the package root and adds it to __all__. |
tests/test_errors.py |
Adds tests for the new exception hierarchy and ensures key behaviors remain unchanged. |
Comments suppressed due to low confidence (1)
src/dbus_fast/errors.py:46
- In these TypeError-derived exceptions, super().init(...) currently resolves to Exception.init (because DBusFastError precedes TypeError in the MRO), so TypeError.init is never invoked. If the goal is to preserve TypeError semantics as closely as possible, prefer ordering the bases as (TypeError, DBusFastError) (and likewise for the ValueError subclasses).
class InvalidBusNameError(DBusFastError, TypeError):
def __init__(self, name: str) -> None:
super().__init__(f"invalid bus name: {name}")
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@bluetoothbot reviewrebase Address the copilot comments |
PR Review — feat(errors): add DBusFastError common base classClean, well-scoped change. Introduces 🟢 Suggestions1. MRO order in multiple inheritance — consider built-in first (`src/dbus_fast/errors.py`, L14-57)Copilot flagged this, but the technical claim is partially incorrect: That said, there's still a defensible reason to swap the order to
Not a blocker — current code is correct — but if you're touching the file to address review, flipping the order is a low-cost improvement that also moots Copilot's concern. 2. Add explicit MRO assertion to lock in base order (`tests/test_errors.py`, L60-87)The existing A single assertion per family would lock this in: def test_value_error_subclass_mro_order() -> None:
mro = SignatureBodyMismatchError.__mro__
# Assert the chosen order — whichever you decide is canonical.
assert mro.index(DBusFastError) < mro.index(ValueError)
def test_type_error_subclass_mro_order() -> None:
mro = InvalidBusNameError.__mro__
assert mro.index(DBusFastError) < mro.index(TypeError)This is what Copilot's second comment was getting at and it's a cheap regression guard. Checklist
SummaryClean, well-scoped change. Introduces Automated review by Kōancdc4432 |
Rebase with requested adjustmentsBranch Changes applied
StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
Five internal sanity-check raises used bare `Exception` / `RuntimeError`, so they escaped `except DBusFastError` introduced in #634. Replace them with a new `InternalError(RuntimeError, DBusFastError)` that keeps backward compatibility (still a `RuntimeError`) while wiring into the common base. Sites: _private/address.py (unknown bus type), message_bus.py (missing proxy object class, missing interface path), signature.py (missing validator for token), _private/marshaller.py ("should not reach here"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
What
Introduce
DBusFastErroras a common base class for every exception raised bydbus-fast.Why
Closes #507. Today, dbus-fast exceptions derive from a mix of
ValueError,TypeError, andException, with no shared ancestor. Applications that want to distinguish dbus-fast errors from other errors must either wrap dbus-fast calls in dedicated try/except blocks or list every error class by name — both clutter caller code.How
DBusFastError(Exception)indbus_fast/errors.py.DBusFastError.ValueError(SignatureBodyMismatchError,InvalidSignatureError,InvalidAddressError,InvalidMessageError,InvalidIntrospectionError) and fromTypeError(InvalidBusNameError,InvalidObjectPathError,InvalidInterfaceNameError,InvalidMemberNameError) use multiple inheritance to preserve the built-in base — existingexcept ValueError/except TypeErrorhandlers keep working.DBusFastErroris exported from the package root.Testing
tests/test_errors.pycovers MRO, isinstance checks for the new base, preservation ofValueError/TypeErrorsemantics, and unchanged error message formatting.pytest -q ...→ 106 passed, 5 skipped).🤖 Generated with Claude Code
Quality Report
Changes: 3 files changed, 154 insertions(+), 13 deletions(-)
Code scan: clean
Tests: failed ([Errno 13] Permission denied: 'pytest')
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline