Deprecation Guide¶
This document tracks deprecated APIs in the SW4RM Python SDK and provides migration guides for transitioning to their replacements.
Deprecation Policy¶
The SW4RM SDK follows these deprecation practices:
- Announcement: Deprecations are announced in minor version releases
- Warning Period: Deprecated APIs emit
DeprecationWarningfor at least one minor version - Removal: Deprecated APIs are removed in the next major version
- Minimum Period: 6-month minimum between deprecation and removal
- Documentation: All deprecations are documented with migration guides
Current Deprecations¶
| Deprecated API | Replacement | Version Deprecated | Removal Target |
|---|---|---|---|
from sw4rm.handoff import HandoffClient | from sw4rm.clients import HandoffClient | v0.5.0 | v1.0.0 |
sw4rm.acks.map_exception_to_error_code() | sw4rm.error_mapping.DEFAULT_MAPPER.map_exception() | v0.5.0 | v1.0.0 |
Migration: HandoffClient Import¶
Background¶
The HandoffClient was originally located in sw4rm.handoff alongside handoff protocol types. To provide a consistent API where all clients are accessible from sw4rm.clients, the client has been moved.
Deprecated Usage¶
# DEPRECATED - will show DeprecationWarning
from sw4rm.handoff import HandoffClient
client = HandoffClient(channel)
response = client.request_handoff(request)
Recommended Usage¶
# NEW - preferred import
from sw4rm.clients import HandoffClient
client = HandoffClient(channel)
response = client.request_handoff(request)
Why Changed¶
All SDK clients are now consolidated under sw4rm.clients for consistency:
from sw4rm.clients import (
RouterClient,
RegistryClient,
SchedulerClient,
HandoffClient, # Now here instead of sw4rm.handoff
NegotiationClient,
ToolClient,
# ... all other clients
)
Migration Steps¶
- Find usages: Search for
from sw4rm.handoff import HandoffClient - Replace import: Change to
from sw4rm.clients import HandoffClient - Verify: The API is identical, only the import path changed
# Find files to update
grep -r "from sw4rm.handoff import.*HandoffClient" --include="*.py"
# Use sed for batch replacement
find . -name "*.py" -exec sed -i \
's/from sw4rm.handoff import HandoffClient/from sw4rm.clients import HandoffClient/g' \
{} \;
Compatibility¶
The old import path continues to work but emits a warning:
DeprecationWarning: Importing HandoffClient from sw4rm.handoff is deprecated.
Use: from sw4rm.clients import HandoffClient
Migration: Error Code Mapping¶
Background¶
The original map_exception_to_error_code() function provided a simple mapping from exceptions to error codes. The new DictErrorCodeMapper class provides more flexibility, including custom mappings and fallback behavior.
Deprecated Usage¶
# DEPRECATED
from sw4rm.acks import map_exception_to_error_code
try:
process_message(envelope)
except Exception as exc:
error_code = map_exception_to_error_code(exc)
send_ack(error_code=error_code)
Recommended Usage¶
# NEW - using the default mapper
from sw4rm.error_mapping import DEFAULT_MAPPER
try:
process_message(envelope)
except Exception as exc:
error_code = DEFAULT_MAPPER.map_exception(exc)
send_ack(error_code=error_code)
Custom Mapping¶
The new system supports custom exception-to-error-code mappings:
from sw4rm.error_mapping import DictErrorCodeMapper
from sw4rm import constants as C
# Define custom mappings
custom_mapper = DictErrorCodeMapper({
MyDatabaseError: C.INTERNAL_ERROR,
MyAuthError: C.PERMISSION_DENIED,
MyRateLimitError: C.BUFFER_FULL,
})
# Use custom mapper
try:
process_message(envelope)
except Exception as exc:
error_code = custom_mapper.map_exception(exc)
Combining Default and Custom Mappings¶
from sw4rm.error_mapping import DictErrorCodeMapper, DEFAULT_MAPPER
from sw4rm import constants as C
# Create custom mapper with fallback to default
class CombinedMapper:
def __init__(self):
self.custom = DictErrorCodeMapper({
MyCustomError: C.VALIDATION_ERROR,
})
self.default = DEFAULT_MAPPER
def map_exception(self, exc: Exception) -> int:
# Try custom first
code = self.custom.map_exception(exc)
if code != C.INTERNAL_ERROR: # Custom found a match
return code
# Fall back to default
return self.default.map_exception(exc)
mapper = CombinedMapper()
Why Changed¶
The new DictErrorCodeMapper provides:
- Customization: Define your own exception-to-error mappings
- Type Safety: Clear protocol for error mapping
- Composition: Combine multiple mappers
- Testability: Inject custom mappers in tests
Migration Steps¶
- Simple replacement: Replace
map_exception_to_error_code(exc)withDEFAULT_MAPPER.map_exception(exc) - Add import: Add
from sw4rm.error_mapping import DEFAULT_MAPPER - Optional customization: Create
DictErrorCodeMapperif you need custom mappings
Detecting Deprecation Warnings¶
Enable Warnings in Development¶
import warnings
# Show all deprecation warnings
warnings.filterwarnings("default", category=DeprecationWarning, module="sw4rm")
# Or make them errors during testing
warnings.filterwarnings("error", category=DeprecationWarning, module="sw4rm")
Run Tests with Warnings¶
# Show deprecation warnings during pytest
pytest -W default::DeprecationWarning
# Fail on deprecation warnings
pytest -W error::DeprecationWarning
# Show SW4RM-specific warnings
pytest -W default::DeprecationWarning:sw4rm
CI/CD Integration¶
Add to your CI configuration to catch deprecations early:
# .github/workflows/test.yml
- name: Test with deprecation warnings
run: pytest -W error::DeprecationWarning --ignore=tests/legacy/
Pre-commit Hook¶
# scripts/check_deprecations.py
import ast
import sys
DEPRECATED_IMPORTS = [
("sw4rm.handoff", "HandoffClient"),
]
DEPRECATED_FUNCTIONS = [
("sw4rm.acks", "map_exception_to_error_code"),
]
def check_file(filepath):
with open(filepath) as f:
tree = ast.parse(f.read())
issues = []
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom):
module = node.module or ""
for alias in node.names:
for dep_module, dep_name in DEPRECATED_IMPORTS:
if module == dep_module and alias.name == dep_name:
issues.append(
f"{filepath}:{node.lineno}: "
f"Deprecated import: {dep_module}.{dep_name}"
)
return issues
if __name__ == "__main__":
all_issues = []
for filepath in sys.argv[1:]:
all_issues.extend(check_file(filepath))
for issue in all_issues:
print(issue)
sys.exit(1 if all_issues else 0)
Version History¶
v0.5.0 (Current)¶
Deprecated:
sw4rm.handoff.HandoffClient- Usesw4rm.clients.HandoffClientsw4rm.acks.map_exception_to_error_code()- Usesw4rm.error_mapping.DEFAULT_MAPPER
v1.0.0 (Planned)¶
To Be Removed:
- All v0.5.0 deprecated APIs
Reporting Issues¶
If you encounter issues during migration:
- Check this documentation for migration steps
- Search existing issues
- Open a new issue with:
- SW4RM version
- Code sample showing the problem
- Error message or unexpected behavior
See Also¶
- SDK Clients - Current client API documentation
- Exceptions Reference - Error handling
- Changelog - Version history