A python library for interacting with HAL+JSON APIs
—
Comprehensive HTTP method support for RESTful operations. RestNavigator provides methods for all standard HTTP verbs with proper error handling, response management, and HAL-specific processing.
Create new resources using POST requests with automatic response handling and navigation.
class HALNavigator:
def create(self, body: dict = None, raise_exc: bool = True, headers: dict = None) -> 'OrphanHALNavigator':
"""
POST request to create a new resource.
Parameters:
- body: Request body data (will be JSON-encoded)
- raise_exc: Whether to raise exceptions on HTTP errors
- headers: Additional headers for this request
Returns:
OrphanHALNavigator containing response data
"""Usage example:
# Create a new user
new_user = api['users'].create({
'username': 'john_doe',
'email': 'john@example.com',
'full_name': 'John Doe'
})
# Check the response status
if new_user: # Truthy if HTTP 2xx status
print("User created successfully")
print("Response data:", new_user.state)
print("Status:", new_user.status)
# Handle errors gracefully
result = api['users'].create({'invalid': 'data'}, raise_exc=False)
if not result:
print("Creation failed:", result.status)
print("Error details:", result.state)Replace entire resources using PUT requests for idempotent create-or-update operations.
class HALNavigator:
def upsert(self, body: dict, raise_exc: bool = True, headers = False) -> 'OrphanHALNavigator':
"""
PUT request for idempotent create/update operations.
Parameters:
- body: Complete resource representation
- raise_exc: Whether to raise exceptions on HTTP errors
- headers: Additional headers for this request
Returns:
OrphanHALNavigator containing response data
"""Usage example:
# Replace entire user resource
updated_user = user.upsert({
'id': 123,
'username': 'john_doe',
'email': 'john.doe@newdomain.com',
'full_name': 'John David Doe',
'status': 'active'
})
# PUT is idempotent - can be called multiple times
user.upsert(complete_user_data)Update specific fields of resources using PATCH requests for partial modifications.
class HALNavigator:
def patch(self, body: dict, raise_exc: bool = True, headers = False) -> 'OrphanHALNavigator':
"""
PATCH request for partial resource updates.
Parameters:
- body: Partial resource data to update
- raise_exc: Whether to raise exceptions on HTTP errors
- headers: Additional headers for this request
Returns:
OrphanHALNavigator containing response data
"""Usage example:
# Update only specific fields
result = user.patch({
'email': 'newemail@example.com',
'last_login': '2023-01-15T10:30:00Z'
})
# Update with custom headers
result = user.patch(
{'status': 'inactive'},
headers={'X-Admin-Override': 'true'}
)Remove resources using DELETE requests with proper response handling.
class HALNavigator:
def delete(self, raise_exc: bool = True, headers: dict = None) -> 'OrphanHALNavigator':
"""
DELETE request to remove the resource.
Parameters:
- raise_exc: Whether to raise exceptions on HTTP errors
- headers: Additional headers for this request
Returns:
OrphanHALNavigator containing response data
"""Usage example:
# Delete a resource
result = user.delete()
# Check if deletion was successful
if result:
print("User deleted successfully")
# Delete with custom headers
admin_user.delete(headers={'X-Force-Delete': 'true'})
# Handle deletion errors
result = user.delete(raise_exc=False)
if result.status[0] == 404:
print("User was already deleted")
elif result.status[0] >= 400:
print("Deletion failed:", result.state)All HTTP operations return OrphanHALNavigator instances that provide access to response data and status information.
class OrphanHALNavigator(HALNavigator):
def __call__(self) -> dict:
"""
Return response state (cannot fetch from server).
Returns:
Response data as dictionary
"""
@property
def parent(self) -> 'HALNavigator':
"""Reference to the navigator this was created from"""# Automatic exception raising (default)
try:
result = api['users'].create(user_data)
print("Success:", result.state)
except HALNavigatorError as e:
print(f"HTTP {e.status}: {e.message}")
print("Response:", e.response.text)
# Manual error checking
result = api['users'].create(user_data, raise_exc=False)
if result: # Check boolean status
print("Success:", result.state)
else:
status_code, reason = result.status
print(f"Failed: {status_code} {reason}")
print("Error details:", result.state)
# Status code specific handling
result = user.delete(raise_exc=False)
if result.status[0] == 204:
print("Deleted successfully (no content)")
elif result.status[0] == 404:
print("Resource not found")
elif result.status[0] >= 400:
print("Deletion failed:", result.state)# Custom content type
result = api['documents'].create(
{'content': 'Document text'},
headers={'Content-Type': 'application/vnd.api+json'}
)
# Working with different response formats
result = api['export'].create({'format': 'csv'})
if result.response.headers.get('content-type') == 'text/csv':
csv_data = result.response.textInstall with Tessl CLI
npx tessl i tessl/pypi-restnavigator