A python library for interacting with HAL+JSON APIs
—
Core navigation functionality that provides the foundation for interacting with HAL+JSON APIs. These components enable link following, resource fetching, and hypermedia traversal.
Creates HAL navigator instances for API roots with shared configuration and session management.
class Navigator:
@staticmethod
def hal(root: str, apiname: str = None, default_curie: str = None,
auth: tuple = None, headers: dict = None, session = None) -> 'HALNavigator':
"""
Create a HAL navigator for the given API root.
Parameters:
- root: API root URL (the only hardcoded URL in your application)
- apiname: Optional name for the API (used in navigator display)
- default_curie: Default CURIE prefix for link relations
- auth: Authentication credentials (tuple for basic auth)
- headers: Default headers to send with all requests
- session: Custom requests Session object for advanced authentication
Returns:
HALNavigator instance for the API root
"""Usage example:
from restnavigator import Navigator
# Basic usage
api = Navigator.hal('https://api.example.com/')
# With authentication and configuration
api = Navigator.hal(
'https://api.example.com/',
apiname='MyAPI',
default_curie='ex',
auth=('username', 'password'),
headers={'User-Agent': 'MyApp/1.0'}
)
# With OAuth2 session
from requests_oauthlib import OAuth2Session
oauth_session = OAuth2Session('client_id', token='access_token')
api = Navigator.hal('https://api.example.com/', session=oauth_session)The primary interface for navigating HAL APIs, following links, and accessing resource state.
class HALNavigator:
def __call__(self, raise_exc: bool = True) -> dict:
"""
Fetch resource state or return cached state.
Parameters:
- raise_exc: Whether to raise exceptions on HTTP errors
Returns:
Resource state as dictionary
"""
def fetch(self, raise_exc: bool = True) -> dict:
"""
Perform GET request and return state, bypassing cache.
Parameters:
- raise_exc: Whether to raise exceptions on HTTP errors
Returns:
Fresh resource state from server
"""
def links(self) -> 'CurieDict':
"""
Returns dictionary of linked navigators by relation.
Returns:
CurieDict mapping link relations to HALNavigator instances
"""
def embedded(self) -> 'CurieDict':
"""
Returns dictionary of embedded navigators by relation.
Returns:
CurieDict mapping embedded relations to HALNavigator instances
"""
def __getitem__(self, args) -> 'HALNavigator':
"""
Navigate relationships using bracket notation.
Parameters:
- args: Link relation(s) to follow, supports chaining
Returns:
HALNavigator for the target resource
"""
def __contains__(self, value: str) -> bool:
"""
Check if link relation exists in links or embedded resources.
Parameters:
- value: Link relation to check for
Returns:
True if relation exists
"""
def __iter__(self) -> 'HALNavigator':
"""
Iterate through paginated resources using 'next' links.
Returns:
Iterator yielding HALNavigator instances
"""
def next(self) -> 'HALNavigator':
"""
Get next navigator in pagination sequence.
Returns:
HALNavigator for next page or None
"""
def docsfor(self, rel: str) -> None:
"""
Open documentation for link relation in browser.
Parameters:
- rel: Link relation to get documentation for
"""class HALNavigator:
@property
def uri(self) -> str:
"""Current resource URI"""
@property
def apiname(self) -> str:
"""API name for display purposes"""
@property
def resolved(self) -> bool:
"""Whether resource has been fetched from server"""
@property
def status(self) -> tuple:
"""HTTP status code and reason phrase"""
@property
def state(self) -> dict:
"""Current resource state data"""
@property
def response(self):
"""HTTP response object from last request"""
@property
def title(self) -> str:
"""Title from self link properties"""
@property
def profile(self) -> str:
"""Profile from self link properties"""
@property
def type(self) -> str:
"""Type from self link properties"""# Basic link following
users = api['users']
user = api['users']['user']
# Chained navigation with single bracket call
user = api['users', 'user']
# Navigation with list indexing
first_user = api['users', 0] # Get first item from users list
# Check if links exist
if 'posts' in user:
posts = user['posts']
# Pagination iteration
for page in api['posts']:
print("Processing page:", page.uri)
# Process page items
break # Prevent infinite iteration
# Working with embedded vs linked resources
api_links = api.links() # Only linked resources
api_embedded = api.embedded() # Only embedded resources
api['relation'] # Searches both links and embeddedInstall with Tessl CLI
npx tessl i tessl/pypi-restnavigator